package xpyunapi

import (
	"bytes"
	"crypto/sha1"
	"encoding/json"
	"fmt"
	"git.rosy.net.cn/baseapi/utils"
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"
	"io/ioutil"
	"net/http"
	"regexp"
	"strconv"
	"strings"
	"time"
	"unicode"
)

/**
 * 发送http的json请求
 *
 * @param url 请求url
 * @param jsonStr 发送的json字符串
 *
 */
func HttpPostJson(url string, data interface{}) *XPYunResp {
	b, err := json.Marshal(&data)
	if err != nil {
		var msg = fmt.Sprintf("json serialize err:%+v", err)
		fmt.Println(msg)
		result := XPYunResp{
			HttpStatusCode: 500,
		}
		return &result
	}

	//var reqMsg = fmt.Sprintf("response result:%+v", string(b))
	//fmt.Println(reqMsg)

	resp, err := http.Post(url, "application/json", bytes.NewBuffer(b))
	if err != nil {
		fmt.Println(err)
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		var msg = fmt.Sprintf("post json error:%+v", err)
		fmt.Println(msg)
	}

	result := XPYunResp{
		HttpStatusCode: resp.StatusCode,
	}

	var content XPYunRespContent
	err = json.Unmarshal(body, &content)
	if err == nil {
		result.Content = &content
	} else {
		var msg = fmt.Sprintf("unmarshal body failed, error:%+v", err)
		fmt.Println(msg)
	}

	return &result
}

/**
 * 哈稀签名
 * @param signSource - 源字符串
 * @return
 */
func Sign(signSource string) string {
	h := sha1.New()
	h.Write([]byte(signSource))
	result := fmt.Sprintf("%x", h.Sum(nil))
	return result
}

//获得毫秒数
func GetMillisecond() int64 {
	return time.Now().UnixNano() / 1e6
}

/**
 * 获得字符串重复
 * @param str - 要进行重复的字符串
 * @param repeatTimes - 重复次数
 */
func StrRepeat(str string, repeatTimes int) string {
	return strings.Repeat(str, repeatTimes)
}

func CalcGbkLenForPrint(data string) int {
	gbk, err := Utf8ToGbk(data)
	if err != nil {
		return 0
	}

	return len(gbk)
}

func CalcAsciiLenForPrint(data string) int {
	return len(data)
}

func Utf8ToGbk(s string) (string, error) {
	reader := transform.NewReader(bytes.NewReader([]byte(s)), simplifiedchinese.GBK.NewEncoder())
	d, e := ioutil.ReadAll(reader)
	if e != nil {
		return "", e
	}
	return string(d), nil
}

//解析返回数据结构体
func GetXpuResponse(data interface{}) *XPYunRespContent {
	retVal := &XPYunRespContent{}
	resultJson, _ := json.Marshal(data)
	decoder := json.NewDecoder(bytes.NewBufferString(string(resultJson)))
	if err := decoder.Decode(&retVal); err != nil {
		return nil
	}
	return retVal
}

const ROW_MAX_CHAR_LEN = 32
const MAX_NAME_CHAR_LEN = 20
const NEX_ROW_CHAR_LEN = 8
const LAST_ROW_MAX_NAME_CHAR_LEN = 16
const MAX_QUANTITY_CHAR_LEN = 6
const MAX_PRICE_CHAR_LEN = 6

const LAST_ROW_MAX_NAME_CHAR_LEN80 = 24 //26
const ROW_MAX_CHAR_LEN80 = 48
const MAX_NAME_CHAR_LEN80 = 27
const MAX_QUANTITY_CHAR_LEN80 = 7

//var orderNameEmpty = StrRepeat(" ", MAX_NAME_CHAR_LEN)
var orderNameEmpty = StrRepeat(" ", NEX_ROW_CHAR_LEN)

//test函数
func FormatPrintOrderItem(foodName string, quantity int, price float64) string {
	//foodNameLen := CalcGbkLenForPrint(foodName)

	quantityStr := strconv.Itoa(quantity)
	quantityLen := CalcAsciiLenForPrint(quantityStr)

	temprice := price / 100
	priceStr := fmt.Sprintf("%.2f", temprice)
	priceLen := CalcAsciiLenForPrint(priceStr)

	subtotalStr := fmt.Sprintf("%.2f", utils.Int2Float64(quantity)*temprice)
	//subtotalLen := CalcAsciiLenForPrint(subtotalStr)

	result := foodName + "<BR>"
	//mod := foodNameLen % ROW_MAX_CHAR_LEN
	//if mod <= LAST_ROW_MAX_NAME_CHAR_LEN {
	//	// 保证各个列的宽度固定，不足部分，利用空格填充
	//	result = result + StrRepeat(" ", MAX_NAME_CHAR_LEN-mod)
	//
	//} else {
	//	// 另起新行
	//	result = result + "<BR>"
	//	result = result + orderNameEmpty
	//}

	result += orderNameEmpty + "x" + quantityStr + StrRepeat(" ", MAX_QUANTITY_CHAR_LEN-quantityLen)
	result += "￥" + priceStr + StrRepeat(" ", MAX_QUANTITY_CHAR_LEN+1-priceLen)
	result += "￥" + subtotalStr
	result += "<BR>"
	return result
}

//正则计算宽度
func CalWidth(str string) int {
	hzc := 0
	for _, v := range str {
		if unicode.Is(unicode.Han, v) {
			hzc++
		}
	}
	updateStr := regexp.MustCompile("[\u4e00-\u9fa5]{1,}").ReplaceAllString(str, "")
	l := len(updateStr)
	fmt.Println(hzc)
	ans := 2*hzc + l
	return ans
}

const (
	MaxLineLength = 30
	LineLength    = 32
	NewLineLength = 28
)

func FormatPrintOrderItemV2(foodName string, quantity, index int) string {
	var (
		restLen     int
		quantityStr = strconv.Itoa(quantity)
		//quantityLen = CalcAsciiLenForPrint(quantityStr)
		foodNameLen = CalWidth(foodName) + 3
		result      = ""
	)
	if foodNameLen >= MaxLineLength {
		if n := foodNameLen / LineLength; n > 0 {
			restLen = foodNameLen % LineLength
		} else {
			restLen = foodNameLen - LineLength
		}
		result += "<HB>" + utils.Int2Str(index) + `.` + foodName + "</HB>"
		result += "<HB>" + StrRepeat(" ", MaxLineLength-restLen) + `x` + quantityStr + "</HB>"
	} else {
		result += "<HB>" + utils.Int2Str(index) + `.` + foodName + StrRepeat(" ", MaxLineLength-foodNameLen) + `x` + quantityStr + "</HB>"
	}
	//result += orderNameEmpty + "x" + quantityStr + StrRepeat(" ", MAX_QUANTITY_CHAR_LEN-quantityLen)
	result += "<BR>"
	return result
}
