package swservice

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha1"
	"crypto/tls"
	"encoding/hex"
	"encoding/json"
	"errors"
	"fmt"
	log "github.com/Sirupsen/logrus"
	"io/ioutil"
	"net"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"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) {
	client := w.NewClient(3)

	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 {
	var transport http.Transport
	if strings.HasPrefix(w.BaseUrl, "https://") {
		transport = http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
			TLSHandshakeTimeout: time.Duration(timeout) * time.Second}
	} else if strings.HasPrefix(w.BaseUrl, "http://") {
		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) {
	client := w.NewClient(3)
	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
	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 {
		//		log.Errorf("Status = %v, err = %v\n", r.StatusCode, err)
		return "", err
	}
	if r.StatusCode != 200 {
		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
}
