package main

import (
	"fmt"
	"log"
	"os"
	"time"
)

type procEchoDef struct {
	chatProcedureID
}

var procEcho = procEchoDef{}

func (m *procEchoDef) init(ss *openIDSessionData) {
	ss.setProcedure(m.getID())
	ss.refreshExpire(600)
}

func (m *procEchoDef) clean(ss *openIDSessionData) {
	ss.Procedure = ""
	//log.Println(*ss)
}

func (m *procEchoDef) start(ss *openIDSessionData, in *InWechatMsg) {
	ss.setKvPair("started at", time.Now().Format("2006/03:04:05"))
}

func (m *procEchoDef) serve(ss *openIDSessionData, in *InWechatMsg) (processed bool) {
	stopEcho := false
	if in.header.MsgType == "text" {
		if in.body.(TextMsg).Content == "结束Echo" || in.body.(TextMsg).Content == "结束echo" {
			stopEcho = true
		}
	}
	if in.header.MsgType == "voice" {
		if in.body.(VoiceMsg).Recognition == "退出退出。" {
			stopEcho = true
		}
	}

	if stopEcho {
		in.replyText("echo 正式结束")
		procEcho.summary(ss)
		procEcho.clean(ss)
	} else {
		ss.refreshExpire(600)
		procEcho.doCommand(ss, in)
	}
	processed = true
	return
}

func (m *procEchoDef) summary(ss *openIDSessionData) {
	msg := ss.getVal("started at")
	allmsg := ss.getVal("msg") //may be too long
	if len(allmsg) > 2000 {
		sub := allmsg[0:2000] + "..."
		allmsg = sub
	}
	msg = msg + "\n" + allmsg
	kfSendTxt(ss.OpenID, msg)
}

func (m *procEchoDef) intro(ss *openIDSessionData, in *InWechatMsg) {
	in.replyText("请输入不同类型的微信信息，比如文字，图片，视频，地址，链接，我们将原样回应您")
	kfSendTxt(ss.OpenID, "10分钟静默之后 Echo将自动结束，\n输入 [结束Echo],或者语音 ‘退出退出', 清除Echo模式")
}

func (m *procEchoDef) doCommand(ss *openIDSessionData, in *InWechatMsg) {
	openID := in.header.FromUserName
	str, err := BuildTextMsg(openID, "default")
	log.Println("echoCommand :" + in.header.MsgType)
	switch in.body.(type) {
	case TextMsg:
		m := in.body.(TextMsg)
		str, err = BuildTextMsg(openID, m.Content+"\n\n关键词 [转接] 将后续信息都转接到 客服 测试版")
		procEcho.recordMsg(ss, "文字:"+m.Content)
		in.replyXML(str)
	case PicMsg:
		m := in.body.(PicMsg)
		str = buildPicMsg(openID, m.MediaId)
		in.replyXML(str)
		procEcho.recordMsg(ss, "图片：..")
	case VoiceMsg:
		m := in.body.(VoiceMsg)
		str = buildVoiceMsg(openID, m.MediaId)
		in.replyXML(str)
		procEcho.recordMsg(ss, "音译："+m.Recognition)
		kfSendTxt(openID, "翻译结果:"+m.Recognition)
	case VideoMsg:
		m := in.body.(VideoMsg)
		str = buildVideoMsg(openID, "e2iNEiSxCX5TV1WbFd0TQMn5lilY3bylh1--lDBwi7I", "航拍春日哈工大", m.MediaId)
		in.replyXML(str)
		procEcho.recordMsg(ss, "视频：..")
	case ShortVideoMsg:
		m := in.body.(ShortVideoMsg)
		str = buildVideoMsg(openID, "e2iNEiSxCX5TV1WbFd0TQMn5lilY3bylh1--lDBwi7I", "航拍春日哈工大", m.MediaId)
		in.replyXML(str)
		procEcho.recordMsg(ss, "小视频：..")
	case LocationMsg:
		m := in.body.(LocationMsg)
		mid := location2MediaID(m.Location_X, m.Location_Y)
		str = buildPicMsg(openID, mid)
		in.replyXML(str)
		url := location2URL(m.Location_X, m.Location_Y)
		kfSendTxt(openID, url+"\n"+fmt.Sprintf("long=%f, lat=%f, scale=%d", m.Location_X, m.Location_Y, m.Scale))
		procEcho.recordMsg(ss, "坐标：..")
	case LinkMsg:
		m := in.body.(LinkMsg)
		str, _ = BuildTextMsg(openID, m.Url)
		in.replyXML(str)
		kfSendTxt(openID, m.Title+m.Description)
		procEcho.recordMsg(ss, "链接："+m.Title)
	case EventMsg:
		procEcho.doEvents(ss, in)
	default:
		str, err = BuildTextMsg(openID, "text message")
	}

	if err != nil {
		log.Println("build response failed")
	}
	return
}

func (m *procEchoDef) doEvents(ss *openIDSessionData, in *InWechatMsg) {
	openID := in.header.FromUserName
	str := ""
	e := in.body.(EventMsg)
	//log.Println("Event = " + m.Event)
	procEcho.recordMsg(ss, "事件："+e.Event)
	switch e.Event {
	case "LOCATION":
		mid := location2MediaID(e.Latitude, e.Longitude)
		str = buildPicMsg(openID, mid)
	case "CLICK":
		str, _ = BuildTextMsg(openID, e.EventKey)
	case "subscribe":
		str, _ = BuildTextMsg(openID, e.EventKey)
	case "unsubscribe":
		str, _ = BuildTextMsg(openID, e.EventKey)
	case "SCAN":
		str, _ = BuildTextMsg(openID, e.EventKey)
	case "VIEW":
		str, _ = BuildTextMsg(openID, e.EventKey)
	case "kf_create_session":
		kfSendTxt(openID, e.KfAccount)
		//str, _ = BuildTextMsg(openID, m.KfAccount) // response msg is ignored by wechat
	case "kf_close_session":
		kfSendTxt(openID, e.KfAccount+"\n close type ="+e.CloseType)
		//str, _ = BuildTextMsg(openID, m.KfAccount+"\n close type ="+m.CloseType) //response msg is ignored by wechat
	case "scancode_waitmsg":
		log.Println(e.ScanCodeInfo.ScanResult)
		log.Println(e.ScanCodeInfo.ScanType)
		msg := fmt.Sprintf("ScanResult =%s, ScanType=%s", e.ScanCodeInfo.ScanResult, e.ScanCodeInfo.ScanType)
		kfSendTxt(openID, msg)
	case "pic_photo_or_album":
		msg := fmt.Sprintf("Count = %d ", e.SendPicsInfo.Count)
		log.Println(e.SendPicsInfo.Count)
		for _, v := range e.SendPicsInfo.PicList.Item {
			log.Println(v.PicMd5Sum)
			kfSendTxt(openID, v.PicMd5Sum)
		}
		kfSendTxt(openID, msg)
	default:
		str, _ = BuildTextMsg(openID, " unknown event:"+e.Event)
	}
	in.replyXML(str)
	return
}

func location2MediaID(lat, long float64) (mediaID string) {
	url := fmt.Sprintf("https://maps.googleapis.com/maps/api/staticmap?center=%f,%f&markers=color:red|label:S|%f,%f&zoom=17&size=1280x2014", lat, long, lat, long)
	file, _, _ := saveURL(url)
	mediaID = uploadImage(file)
	os.Remove(file)
	return
}

func location2URL(lat, long float64) (url string) {
	url = fmt.Sprintf("http://maps.google.com/maps?z=12&t=m&q=loc:%f+%f", lat, long)
	log.Println(url)
	return
}

func (m *procEchoDef) recordMsg(ss *openIDSessionData, newmsg string) {
	msg := ss.getVal("msg")
	msg = msg + newmsg + "\n"
	ss.setKvPair("msg", msg)
}
