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"
	"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 (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()
	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) Sign(message string) string {
	mac := hmac.New(sha1.New, []byte(w.Appsecret))
	mac.Write([]byte(message))
	res := mac.Sum(nil)
	return hex.EncodeToString(res)
}

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 || r.StatusCode != 200 {
		log.Errorf(" err = %v\n", err)
		return nil, err
	}

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