package main

import (
	pb "WorldTester/pb"
	"bytes"
	"common/logger"
	"encoding/binary"
	"log"
	"math/rand"

	"net"
	"strconv"
	"time"

	"github.com/golang/protobuf/proto"
)

type CommandItem struct {
	CommandID   int
	CommandDesc string
}

type CommandItemArray []*CommandItem

func (r CommandItemArray) Len() int      { return len(r) }
func (r CommandItemArray) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
func (r CommandItemArray) Less(i, j int) bool {
	if r[i].CommandID < r[j].CommandID {
		return true
	}
	return false
}

func RemoveDuplicates(elements []int) []int {
	encountered := map[int]bool{}
	result := []int{}

	for v := range elements {
		if encountered[elements[v]] == true {
		} else {
			encountered[elements[v]] = true
			result = append(result, elements[v])
		}
	}
	return result
}

type CommandHandler func(conn net.Conn, args []string)

type CommandHandlerInfo struct {
	desc    string
	handler CommandHandler
}

var (
	map_commands        = make(map[int]CommandHandlerInfo)
	m_matchuid   uint32 = 0
	m_roomid     uint32 = 0
	m_playerid   uint32 = 0
	m_seq        uint32 = 0
	m_clubseq    uint32 = 0
	crack_str           = "1234567890~!@#$%^&*()_+|}{:L?><bxcnzcaasuDDYCTDGHSAWEXXBVM>><?:L{}PITEQQ!~456abcedfsfsfdilekso"
)

func registCommandHandler(command_id int, command_desc string, handler CommandHandler) {
	var info CommandHandlerInfo
	info.desc = command_desc
	info.handler = handler
	map_commands[command_id] = info
}

func init() {
}

func SendLogin(player *PlayerInfo) {
	var req pb.RequestLogon
	req.Version = "1.1.36"
	req.Token = "LeaveMeAlone"
	player.state = STATE_PLAYER_INIT
	player.seq++
	SendMessage(player.conn, player.seq, player.uid, player.rid, pb.MSGID_MsgID_Logon_Request, &req)
}

func SendPurchaseClubLevel(player *PlayerInfo, clubid int32) {
	var req pb.RequestPurchaseClubLevel
	req.ClubId = clubid
	req.TypeId = 5 //5 star
	player.seq++
	SendMessage(player.conn, player.seq, player.uid, player.rid, pb.MSGID_MsgID_PurchaseClubLevel_Request, &req)
}

func SendRechargeClubFund(player *PlayerInfo, clubid int32) {
	var req pb.RequestRechargeClubFund
	req.Param = new(pb.RechargeClubFundParams)
	req.Param.ClubId = clubid
	req.Param.BuyCount = 1
	player.seq++
	SendMessage(player.conn, player.seq, player.uid, player.rid, pb.MSGID_MsgID_RechargeClubFund_Request, &req)
}

func SendModifyClubInfo(player *PlayerInfo, clubid int32) {
	log.Println("SendModifyClubInfo")
	var req pb.RequestModifyClubInfo
	req.Param = new(pb.ModifyClubInfoParams)
	req.Param.ClubId = clubid
	req.Param.ClubUid = int32(player.uid)
	player.seq++
	req.Param.ClubName = "robet new" + strconv.Itoa(int(player.seq))
	req.Param.ClubDescrption = "robet new description"

	SendMessage(player.conn, player.seq, player.uid, player.rid, pb.MSGID_MsgID_ModifyClubInfo_Request, &req)
}

func SendJoinClubReply(player *PlayerInfo, result int32, clubId int32, uid int32) {
	log.Println("SendJoinClubReply")
	var req pb.ReplyJoinClub
	req.Result = result
	req.ClubId = clubId
	req.Uid = uid
	req.Reason = "a valid reason"
	player.seq++
	SendMessage(player.conn, player.seq, player.uid, player.rid, pb.MSGID_MsgID_JoinClub_Reply, &req)
}

func SendCreateClub(player *PlayerInfo) {
	log.Println("SendCreateClub")
	var req pb.RequestCreateClub
	req.Param = new(pb.ClubParams)

	m_clubseq++
	req.Param.ClubName = "阿明正俱乐部" + strconv.Itoa(int(m_clubseq))
	req.Param.ClubArea = "上海"
	req.Param.ClubIcon = "阿明正.ico"

	player.seq++

	SendMessage(player.conn, player.seq, player.uid, player.rid, pb.MSGID_MsgID_CreateClub_Request, &req)
}

func SendJoinClub(player *PlayerInfo) {


	log.Println("cids:", 1)


}


func SendMessage(conn net.Conn, seq uint32, uid uint32, rid uint32, msgid pb.MSGID, msg interface{}) {
	tmp, err := proto.Marshal(msg.(proto.Message))
	if err != nil {
		logger.Info("marshal msgid:%v response body error:%v", msgid, err)
		return
	}
	if conn == nil {
		logger.Info("conn is nil for uid:%v rid:%v msgid:%v", uid, rid, msgid)
		return
	}
	total_len := len(tmp) + int(Min_Message_Size)
	bys := new(bytes.Buffer)
	binary.Write(bys, binary.BigEndian, uint16(total_len))
	binary.Write(bys, binary.BigEndian, uint16(msgid))
	binary.Write(bys, binary.BigEndian, uint32(seq))
	binary.Write(bys, binary.BigEndian, uint32(uid))
	binary.Write(bys, binary.BigEndian, uint32(rid))
	logger.Info("--> send message header, len:%v roomid:%v msgid:%v seq:%v uid:%v",
		total_len, rid, msgid, seq, uid)
	var buf []byte
	if do_trash {
		r := rand.Intn(1000)
		if r < 300 {
			trash := GetTranshBytesByLen(total_len)
			buf = append(buf, trash...)
			logger.Info("***** do trash for msgid:%v uid:%v rid:%v", pb.MSGID(msgid), uid, rid)
		} else {
			buf = append(bys.Bytes(), tmp...)
		}
	} else {
		buf = append(bys.Bytes(), tmp...)
	}

	conn.SetWriteDeadline(time.Now().Add(1 * time.Second))
	_, err = conn.Write(buf)
	if err != nil {
		logger.Info("uid:%+v rid:%+v msgid:%+v send socket err:%+v",
			uid, rid, msgid, err)
	}
}

func SendGetClubMemberSnapshotList(player *PlayerInfo, ClubId int32) {
	log.Println("SendGetClubMemberSnapshotList")
	var req pb.RequestClubMemberSnapshotList
	req.Param = new(pb.ClubMemberSnapshotListParams)
	req.Param.ClubId = ClubId
	req.Param.ClubUid = int32(player.uid)
	player.seq++
	SendMessage(player.conn, player.seq, player.uid, player.rid, pb.MSGID_MsgID_ClubMemberSnapshotList_Request, &req)
}

func SendModifyClubMember(player *PlayerInfo, ClubId int32, targetid int32) {
	log.Println("SendModifyClubMember")
	var req pb.RequestModifyClubMember
	req.Param = new(pb.ModifyClubMemberParams)
	req.Param.ClubId = ClubId
	req.Param.ClubUid = int32(player.uid)
	req.Param.ActionType = 0
	req.Param.TargetId = targetid
	player.seq++
	SendMessage(player.conn, player.seq, player.uid, player.rid, pb.MSGID_MsgID_ModifyClubMember_Request, &req)
}

func SendGrantClubFund(player *PlayerInfo, ClubId int32, targetid int32) {
	log.Println("SendGrantClubFund")
	var req pb.RequestGrantClubFund
	req.Param = new(pb.GrantClubFundParams)
	req.Param.ClubId = ClubId
	req.Param.ClubUid = int32(player.uid)
	req.Param.Amount = 100
	req.Param.TargetId = targetid
	player.seq++
	SendMessage(player.conn, player.seq, player.uid, player.rid, pb.MSGID_MsgID_GrantClubFund_Request, &req)
}
