package main

import (
	. "commonapi"
	"crypto/sha1"
	"encoding/hex"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"

	simplejson "github.com/go-simplejson"
)

var handler = map[string]func(w http.ResponseWriter, r *http.Request, js *simplejson.Json, body []byte) int{} /*{

	QUERYTRANSID:     commonFunc,
	QUERYBLOCKID:     commonFunc,
	QUERYADDRESS:     commonFunc,
	QUERYBLOCKINFO:   commonFunc,
	QUERYBLOCKHEIGHT: commonFunc,
}*/

func init() {
	for k, _ := range Handler {
		handler[k] = commonFunc
	}
}

func commonHandler(w http.ResponseWriter, r *http.Request) {

	var ret = 0
	defer func() {
		if ret != 0 {
			errresp := fmt.Sprintf(`{"errcode":%v,"msg":"%v"}`, ret, GetErrMsg(ret, nil))
			w.Write([]byte(errresp))
			log.Error("send resp:%v", errresp)
			return
		}
	}()

	path := r.URL.Path

	defer r.Body.Close()
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		ret = INNER_ERR
		log.Error("err:%s", err.Error())
		return
	}

	log.Debug("read body:%v", string(body))
	js, err := simplejson.NewJson(body)
	if err != nil {
		ret = FORMAT_ERR
		log.Error("err:%s", err.Error())
		return
	}

	timestamp := js.Get("timestamp").MustString()
	signature := js.Get("signature").MustString()

	var ok bool
	if ret, ok = checkPermission(timestamp, signature, []byte(path)); !ok {

		log.Error("check signature err")
		return
	}
	if _, ok := handler[path]; !ok {

		w.WriteHeader(404)
		ret = NO_AUTH
		log.Error("no path,invalid path:%v", path)
		return
	}
	log.Debug("path:%v", path)
	ret = handler[path](w, r, js, body)
	return

}

func commonFunc(w http.ResponseWriter, r *http.Request, js *simplejson.Json, body []byte) int {

	cointype := js.Get("cointype").MustString()
	taskH := NewtaskHandler()

	task := &taskInfo{
		cointype:  cointype,
		jshandler: js,
		urlpath:   r.URL.Path,
		resp:      taskH,
	}

	chanindex := rand.Int31n(100) % int32(CPUNUM)

	taskChan[chanindex] <- task

	resp, err := taskH.waitProcessData()
	if err != nil {

		return TIME_OUT
	}

	w.Write(resp)
	log.Debug("resp write:%v", string(resp))
	return OK
}

func checkSignature(body []byte, timestamp, signature string) bool {

	sha1Contain := sha1.New()
	byteSha1 := append(body, append([]byte(timestamp), []byte("coinsapi^&#@(*33")...)...)
	sha1Contain.Write(byteSha1)
	localSig := hex.EncodeToString(sha1Contain.Sum(nil))
	log.Debug("caculate local signature:%v", localSig)
	return signature == localSig

}

func checkPermission(timestamp, signature string, body []byte) (int, bool) {

	// modify by hyb  cancel checkPermission
	//if checkSignature(body, timestamp, signature) == false {
	//	return NO_AUTH, false
	//}
	return OK, true
}
