package swservice

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha1"
	"encoding/hex"
	"encoding/json"
	"errors"
	"fmt"
	log "github.com/Sirupsen/logrus"
	"io/ioutil"
	"net"
	"net/http"
	"net/url"
	"strconv"
	"time"
)

func dailTimeout(network, addr string) (net.Conn, error) {
	//	default_timeout := time.Duration(theSession.DefaultTimeout) * time.Second
	default_timeout := time.Duration(3) * time.Second
	return net.DialTimeout(network, addr, default_timeout)
}

type WebSession struct {
	AppId          string
	TermId         string
	Appsecret      string
	BaseUrl        string
	DefaultTimeout int
	session_key    string
}

func safe_get_json_int(value interface{}) int {
	if value == nil {
		return 0
	}
	s := fmt.Sprintf("%v", value)
	if i, err := strconv.Atoi(s); err != nil {
		return 0
	} else {
		return i
	}
}

type ServiceResponse struct {
	RetCode int
	RetMsg  string
	Result  map[string]interface{}
}

func NewServiceResponseFromJson(json_data interface{}) *ServiceResponse {
	if json_data == nil {
		return nil
	}
	res := &ServiceResponse{}
	res.Result = json_data.(map[string]interface{})
	res.RetCode = safe_get_json_int(res.Result["retcode"])
	res.RetMsg = res.GetStrValue("retmsg")
	return res
}
func (r *ServiceResponse) GetIntValue(name string) int {
	return safe_get_json_int(r.Result[name])
}

func (r *ServiceResponse) GetStrValue(name string) string {
	if s, ok := r.Result[name]; ok {
		return fmt.Sprintf("%v", s)
	} else {
		return ""
	}
}

func (r *ServiceResponse) GetFloatValue(name string) float64 {
	if s, ok := r.Result[name]; ok {
		t := fmt.Sprintf("%v", s)
		if f, err := strconv.ParseFloat(t, 64); err != nil {
			return 0.0
		} else {
			return f
		}
	} else {
		return 0.0
	}
}

func (w *WebSession) DoGet(uri string, params map[string]string) (*http.Response, error) {
	transport := http.Transport{Dial: dailTimeout}

	client := http.Client{Transport: &transport}

	full_url := w.BaseUrl + uri

	vl := url.Values{}

	if params != nil {
		for k, v := range params {
			vl.Add(k, v)
		}
	}
	full_url = full_url + "?" + vl.Encode()
	//	fmt.Printf("%v\n", full_url)
	return client.Get(full_url)
}

func (w *WebSession) GetTimestamp() string {
	t := time.Now()
	return fmt.Sprintf("%04d%02d%02d%02d%02d%02d", t.Year(), t.Month(), t.Day(),
		t.Hour(), t.Minute(), t.Second())
}

func (w *WebSession) SignWithKey(key, message string) string {
	mac := hmac.New(sha1.New, []byte(key))
	mac.Write([]byte(message))
	res := mac.Sum(nil)
	return hex.EncodeToString(res)
}
func (w *WebSession) Sign(message string) string {
	return w.SignWithKey(w.Appsecret, message)
}

func (w *WebSession) NewClient(timeout int) *http.Client {
	transport := http.Transport{Dial: func(network, addr string) (net.Conn, error) {
		default_timeout := time.Duration(timeout) * time.Second
		return net.DialTimeout(network, addr, default_timeout)
	}}

	return &http.Client{Transport: &transport}
}
func (w *WebSession) DoPost(uri string, param map[string]string) (*http.Response, error) {
	transport := http.Transport{Dial: dailTimeout}
	client := &http.Client{Transport: &transport}
	param["app_id"] = w.AppId
	//	param["term_id"] = w.TermId
	param["sign_method"] = "HMAC"
	param["session_key"] = w.session_key
	ts := w.GetTimestamp()
	param["timestamp"] = ts
	param["sign"] = w.Sign(w.AppId + w.TermId + w.session_key + ts)

	full_url := w.BaseUrl + uri
	//	log.Debugf("Url=%v", full_url)
	data, err := json.Marshal(param)
	if err != nil {
		return nil, err
	}
	var r *http.Response
	r, err = client.Post(full_url, "application/json", bytes.NewReader(data))
	if err != nil || r.StatusCode != 200 {
		log.Errorf("Status=%v, err=%v", r, err)
	}
	return r, err
}

func (w *WebSession) Auth() error {
	token, err := w.getAuthToken()
	if err != nil {
		return err
	}
	err = w.getAppAccessKey(token)
	if err != nil {
		return err
	}
	return nil
}

func NewSession(appid, appsecret, termid, baseurl string, timeout int) *WebSession {
	return &WebSession{
		AppId:          appid,
		Appsecret:      appsecret,
		TermId:         termid,
		BaseUrl:        baseurl,
		DefaultTimeout: timeout,
	}
}

func (w *WebSession) getAuthToken() (string, error) {
	type FormJson struct {
		AppId       string `json:"app_id"`
		TermId      string `json:"term_id"`
		AccessToken string `json:"access_token"`
	}

	uri := fmt.Sprintf("/authservice/getauth/%v/getaccesstoken", w.AppId)

	params := make(map[string]string)
	params["term_id"] = w.TermId
	r, err := w.DoGet(uri, params)

	if err != nil || r.StatusCode != 200 {
		fmt.Println("here")
		//		log.Errorf("Status = %v, err = %v\n", r.StatusCode, err)
		return "", errors.New("请求失败")
	}

	body, err := ioutil.ReadAll(r.Body)
	r.Body.Close()

	s := &FormJson{}
	err = json.Unmarshal(body, &s)
	if err != nil {
		log.Errorf("json unmarshal err %v", err)
		return "", errors.New("解析失败")
	}
	return s.AccessToken, nil
}
func (w *WebSession) getAppAccessKey(token string) error {
	type FormJson struct {
		AppId      string `json:"app_id"`
		TermId     string `json:"term_id"`
		SessionKey string `json:"session_key"`
		CardKey    string `json:"card_key"`
	}

	uri := fmt.Sprintf("/authservice/getauth/%v", w.AppId)

	params := make(map[string]string)
	params["term_id"] = w.TermId
	params["access_token"] = token
	params["timestamp"] = w.GetTimestamp()
	params["v"] = "1"
	params["sign"] = w.Sign(token + params["timestamp"])
	params["sign_method"] = "HMAC"

	r, err := w.DoGet(uri, params)
	if err != nil || r.StatusCode != 200 {
		log.Errorf(" err = %v\n", err)
		return err
	}

	body, err := ioutil.ReadAll(r.Body)
	r.Body.Close()

	s := &FormJson{}
	err = json.Unmarshal(body, &s)
	if err != nil {
		log.Errorf("json unmarshal err %v", err)
	}
	w.session_key = s.SessionKey
	return nil
}

func (w *WebSession) CallYKTApi(request *MessageWriter) (*MessageReader, error) {
	call_data := request.Serialize()
	params := make(map[string]string)
	params["funcdata"] = call_data
	r, err := w.DoPost("/ecardservice/ecardapi", params)

	if err != nil {
		log.Errorf(" err = %v\n", err)
		return nil, err
	}

	if r.StatusCode != 200 {
		return nil, errors.New(fmt.Sprintf("Request StatusCode:%v", r.StatusCode))
	}

	body, err := ioutil.ReadAll(r.Body)
	r.Body.Close()
	return NewMessageReader(body), nil
}

func (w *WebSession) CallService(path string, params map[string]interface{},
	sign_field []string, timeout int) (response *ServiceResponse, err error) {

	return w.CallService2(path, params, timeout, sign_field...)
}

func (w *WebSession) CallService2(path string, params map[string]interface{}, timeout int,
	sign_field ...string) (response *ServiceResponse, err error) {
	client := w.NewClient(timeout)
	err = nil
	params["app_id"] = w.AppId
	params["term_id"] = w.TermId
	ts := w.GetTimestamp()
	params["timestamp"] = ts

	vl := &url.Values{}
	for k, v := range params {
		vl.Set(k, fmt.Sprintf("%v", v))
	}

	sign_data := ""
	for _, k := range sign_field {
		if v, ok := params[k]; ok {
			sign_data += fmt.Sprintf("%v", v)
		}
	}
	sign_data += ts + w.session_key
	vl.Set("sign_method", "HMAC")
	log.Debugf("Sign: key[%v] data[%v]\n", w.session_key, sign_data)
	vl.Set("sign", w.SignWithKey(w.Appsecret, sign_data))

	full_url := w.BaseUrl + path
	log.Debugf("CallService: %v\n", full_url)
	var r *http.Response
	r, err = client.Post(full_url, "application/x-www-form-urlencoded",
		bytes.NewReader([]byte(vl.Encode())))
	if err != nil {
		log.Errorf("Status=%v, err=%v", r, err)
		return
	}
	if r.StatusCode != 200 {
		log.Errorf("Request Error %v\n", r.StatusCode)
		err = errors.New(fmt.Sprintf("Request Error, StatusCode : %v", r.StatusCode))
		return
	}
	body, err := ioutil.ReadAll(r.Body)
	r.Body.Close()
	var s interface{}
	err = json.Unmarshal(body, &s)
	if err != nil {
		log.Errorf("json unmarshal err %v", err)
		return
	}
	response = NewServiceResponseFromJson(s)
	return
}
