package main

import (
	"../log"
	"../nnet"
	"../nt"
	pb "../protos"
	"../rpc"
	"../utils"
	"encoding/json"
	"go.uber.org/zap"
	"time"
)

func LoginPostStatus(ses nnet.ISession) {
	cmd := &S_Req{
		Cmd: "status",
		Params: &S_Status{
			Id:     nt.InstConf.Id,
			Ip:     nt.InstConf.AgHost,
			Port:   nt.InstConf.AgPort,
			Cap:    2000,
			Active: Server.GetSessionNum(),
		},
	}

	data, err := json.Marshal(cmd)
	if nil != err {
		log.Warn("LoginStatus", zap.Error(err))
		return
	}
	pkt := NewLoginPacket(data)

	err = ses.AWrite(pkt, 0)
	if nil != err {
		log.Warn("LoginStatus", zap.Error(err))
		return
	}
}

func LoginPostUpdatePassword(guid uint64, ses nnet.ISession, password string) error {
	bytes, err := json.Marshal(utils.H{
		"cmd": "changep",
		"params": utils.H{
			"guid":     guid,
			"password": password,
		},
	})
	if nil != err {
		log.Error("LoginPostUpdatePassword", zap.Error(err))
		return err
	}

	// 等待返回的超时处理
	tm := utils.AsyncWait(5*time.Second, func(p interface{}) {
		sl := &pb.S_UpdatePassword{Ec: int32(pb.ErrCode_UNKNOWN)}
		SendToClient(ses, guid, sl)
		log.Error("UpdatePassword timeout", zap.Uint64("guid", guid))
		// 保存超时句柄
		err = LoginStatus.VerifyTimeout.Remove(guid)
		if nil != err {
			log.Warn("timeout", zap.Uint64("guid", guid), zap.Error(err))
		}
	}, nil)

	// 保存超时句柄
	err = LoginStatus.VerifyTimeout.Save(guid, tm)
	if nil != err {
		log.Warn("Save", zap.Uint64("guid", guid), zap.Error(err))
	}
	return SendToLogin(bytes)
}

func LoginPostUpdateUserinfo(guid uint64, settings *pb.C_UserSettings) error {
	bytes, err := json.Marshal(utils.H{
		"cmd": "alter",
		"params": utils.H{
			"guid":     guid,
			"nickname": settings.Nickname,
			"icon":     settings.Icon,
			"qq":       settings.Qq,
			"wx":       settings.Wechat,
		},
	})
	if nil != err {
		log.Error("LoginPostUpdateUserinfo", zap.Error(err))
		return err
	}
	return SendToLogin(bytes)
}

// 用户绑定手机号
func LoginPostBindPhone(guid uint64, ses nnet.ISession, data *pb.C_BindPhone) error {
	bytes, err := json.Marshal(utils.H{
		"cmd": "upgrade",
		"params": utils.H{
			"guid":     guid,
			"phone":    data.Phone,
			"password": data.Password,
		},
	})
	if nil != err {
		log.Error("LoginPostUpdateUserinfo", zap.Error(err))
		return err
	}

	// 等待返回的超时处理
	tm := utils.AsyncWait(5*time.Second, func(p interface{}) {
		sl := &pb.S_BindPhone{Ec: int32(pb.ErrCode_UNKNOWN)}
		SendToClient(ses, guid, sl)

		log.Error("BindPhone timeout", zap.Uint64("guid", guid))

		// 保存超时句柄
		err = LoginStatus.VerifyTimeout.Remove(guid)
		if nil != err {
			log.Warn("timeout", zap.Uint64("guid", guid), zap.Error(err))
		}
	}, nil)

	// 保存超时句柄
	err = LoginStatus.VerifyTimeout.Save(guid, tm)
	if nil != err {
		log.Warn("Save", zap.Uint64("guid", guid), zap.Error(err))
	}

	return SendToLogin(bytes)
}

// 向登录服务器做客户端登录验证
// save: 返回信息是否需要保存
// ses : 客户端连接的 session
func LoginPostAuth(guid uint64, token string, save bool, ses nnet.ISession) error {
	bytes, err := json.Marshal(&rpc.RpcArgs{
		Cmd: "verify",
		Params: &S_AuthCheck{
			Guid:  guid,
			Token: token,
		},
	})
	if nil != err {
		log.Error("json.Marshal", zap.Error(err))
		return err
	}
	if save {
		// 保存标记
		ServerStatus.NewUserFlag.Save(guid, 1)
	}

	// 等待返回的超时处理
	tm := utils.AsyncWait(5*time.Second, func(p interface{}) {
		sl := &pb.S_Login{Ec: int32(pb.ErrCode_TIMEOUT)}
		OnLoginAuthFinished(guid, ses, sl)
		log.Warn("Verify timeout", zap.Uint64("guid", guid))
		ServerStatus.NewUserFlag.Remove(guid)
	}, ses)

	// 保存临时 session
	iold_ses, err := ServerStatus.TmpSessions.Peek(guid)
	if err != nil {
		ServerStatus.TmpSessions.Save(guid, ses)
	} else {
		if old_ses, ok := iold_ses.(nnet.ISession); ok {
			KillUserSession(guid, old_ses, pb.ReasonDisconn_DUP)
		}
	}

	// 保存超时句柄
	err = LoginStatus.VerifyTimeout.Save(guid, tm)
	if nil != err {
		log.Warn("Save", zap.Uint64("guid", guid), zap.Error(err))
	}

	return SendToLogin(bytes)
}

func SendToLogin(data []byte) error {
	//login_ses, err := Login.RandSession()
	login_ses, err := Login.GetSession(1)
	if err != nil {
		log.Error("login.RandSession", zap.Error(err))
		return err
	}
	err = login_ses.AWrite(NewKgPacket(data), 0)
	if nil != err {
		log.Error("login.Awrite", zap.Error(err))
	}
	return err
}
