﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Net;
using System.Threading;
using System.Net.Sockets;
using System.Text;
using System.IO;

public class Manager : MonoBehaviour
{
    // Start is called before the first frame update
    public GameController Controller;
    public Transform[] CamPos;
    public float time;
    public InputField Nickname;
    public Text LobbyNickname;
    public GameObject[] UIPanels;
    public Text Opponent,server,ongame_self,uiDbgMT;
    public Button MatchBtn;
    public Toggle blind;
    GameState[,] gameStateBackup;
    byte matchID;
    Team selfTeam;
    int lastestFrame;
    int matchToken;

    Socket socket; //目标socket
    EndPoint clientEnd; //客户端
    IPEndPoint ipEnd; //侦听端口
    string recvStr; //接收的字符串
    string sendStr; //发送的字符串
    byte[] sendData = new byte[1024]; //发送的数据，必须为字节
    byte[] recvData = new byte[1024];
    int recvLen; //接收的数据长度
    Thread connectThread; //连接线程


    Vector3 originalPos,targetPos;
    Quaternion originalRota, targetRota;
    float beginTime;
    bool onGoing;

    List<byte[]> recvMDataa = new List<byte[]>();
    void Start()
    {
        Controller.gm = this;
    }

    // Update is called once per frame
    public void Click_L()
    {
        originalPos = Camera.main.transform.position;
        originalRota = Camera.main.transform.rotation;
        targetPos = CamPos[0].position;
        targetRota = CamPos[0].rotation;
        beginTime = Time.time;
        onGoing = true;
    }
    public void Click_W()
    {
        originalPos = Camera.main.transform.position;
        originalRota = Camera.main.transform.rotation;
        targetPos = CamPos[1].position;
        targetRota = CamPos[1].rotation;
        beginTime = Time.time;
        onGoing = true;
    }
    public void Click_B()
    {
        originalPos = Camera.main.transform.position;
        originalRota = Camera.main.transform.rotation;
        targetPos = CamPos[2].position;
        targetRota = CamPos[2].rotation;
        beginTime = Time.time;
        onGoing = true;
    }
    public void Click_Connect()
    {
        InitSocket(server.text);
        if (Nickname.text == null || Nickname.text == "")
        {
            Nickname.text = System.Guid.NewGuid().ToString();
        }
        LobbyNickname.text = Nickname.text;
        ongame_self.text = Nickname.text;
        SocketSend(System.Text.Encoding.Default.GetBytes("Login|||"+Nickname.text));
    }
    public void Click_Matchmake()
    {
        SocketSend(new byte[] { 99, matchID });
    }


    void Update()
    {
        if (recvMDataa.Count > 0)
        {
            SocketRecvMain(recvMDataa[0]);
            recvMDataa.RemoveAt(0);
        }

        /*if (Input.GetKeyDown(KeyCode.L))
        {
            Click_L();
        }
        if (Input.GetKeyDown(KeyCode.B))
        {
            Click_B();
        }
        if (Input.GetKeyDown(KeyCode.W))
        {
            Click_W();
        }*/
        float prog = (Time.time - beginTime) / time;
        if (prog > 1) prog = 1;
        if (onGoing == true)
        {
            Camera.main.transform.rotation = Quaternion.Lerp(originalRota, targetRota, Mathf.SmoothStep(0, 1, prog));
            Camera.main.transform.position = Vector3.Lerp(originalPos, targetPos, Mathf.SmoothStep(0,1,prog));
            if (prog >=1) onGoing = false;
        }
    }
    void InitSocket(string domain)
    {
        // 定义侦听端口,侦听任何IP
        Random.InitState((int)GetTimeStamp());
        ipEnd = new IPEndPoint(IPAddress.Any, Random.Range(2000, 9000));
        //定义套接字类型,在主线程中定义
        socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        //服务端需要绑定ip
        socket.Bind(ipEnd);
        //定义客户端
        IPHostEntry hostInfo = Dns.GetHostEntry(domain);
        //Debug.Log(hostInfo.AddressList[0].ToString());
        IPEndPoint sender = new IPEndPoint(IPAddress.Parse(hostInfo.AddressList[0].ToString()), 9001);
        clientEnd = (EndPoint)sender;

        //开启一个线程连接，必须的，否则主线程卡死
        connectThread = new Thread(new ThreadStart(SocketReceive));
        connectThread.Start();
    }
    public static System.Int64 GetTimeStamp()
    {
        System.TimeSpan ts = System.DateTime.UtcNow - new System.DateTime(1970, 1, 1, 0, 0, 0, 0);
        return System.Convert.ToInt64(ts.TotalMilliseconds);
    }
    void SocketSend(byte[] Data)
    {
        //清空发送缓存
        sendData = new byte[1024];
        //数据类型转换
        sendData = Data;
        //发送给指定客户端
        socket.SendTo(Data, Data.Length, SocketFlags.None, clientEnd);
    }
    void SocketReceive()
    {
        //进入接收循环
        while (true)
        {
            //对data清零
            recvData = new byte[1024];
            //获取客户端，获取客户端数据，用引用给客户端赋值
            recvLen = socket.ReceiveFrom(recvData, ref clientEnd);
            System.Array.Resize(ref recvData, recvLen);
            recvMDataa.Add(recvData);
            //System.IO.MemoryStream m = new System.IO.MemoryStream(recvData);
            //m.Close();
        }
    }
    void SocketQuit()
    {
        //关闭线程
        if (connectThread != null)
        {
            connectThread.Interrupt();
            connectThread.Abort();
        }
        //最后关闭socket
        if (socket != null)
            socket.Close();
    }
    public void SendMove(int fx, int fy, int tx, int ty)
    {
        byte[] b = new byte[32];
        MemoryStream ms = new MemoryStream(b,true);
        ms.WriteByte(100);
        ms.Write(System.BitConverter.GetBytes(lastestFrame+1), 0, 4);
        ms.Write(System.BitConverter.GetBytes(fx), 0, 4);
        ms.Write(System.BitConverter.GetBytes(fy), 0, 4);
        ms.Write(System.BitConverter.GetBytes(tx), 0, 4);
        ms.Write(System.BitConverter.GetBytes(ty), 0, 4);
        //ms.Write(System.BitConverter.GetBytes((int)selfTeam), 24, 4);
        SocketSend(b);
        gameStateBackup = Controller.gameState;
        //Controller.Move(fx,fy,tx,ty);
    }
    public void Blinder()
    {
        if (blind.isOn)
        {
            Controller.BroadcastMessage("BlindChangeOn",SendMessageOptions.DontRequireReceiver);
            return;
        }
        Controller.BroadcastMessage("BlindChangeOff", SendMessageOptions.DontRequireReceiver);

    }
    public void ClickBack()
    {
        Controller.FinshGame();
    }
    void SocketRecvMain(byte[] recvData)
    {
        if (recvData[0] == 101) //Logined
        {
            matchToken = System.BitConverter.ToInt32(recvData, 1);
            uiDbgMT.text = matchToken.ToString();
            matchID = recvData[1];
            UIPanels[0].SetActive(false);
            UIPanels[1].SetActive(true);
        }
        if (recvData[0] == 102)//Matched
        {
            UIPanels[1].SetActive(false);
            UIPanels[2].SetActive(true);
            Opponent.text = System.Text.Encoding.Default.GetString(recvData, 2, 128);
            lastestFrame = 0;
            if (recvData[1] == 0)
            {
                selfTeam = Team.Black;
                Click_B();
            }
            else
            {
                selfTeam = Team.White;
                Click_W();
            }
            Controller.selfTeam = selfTeam;
            Controller.turn = Team.White;
            Controller.Initiate();
        }
        if (recvData[0] == 100) //Move
        {
            int fx, fy, tx, ty, frameID;
            frameID = System.BitConverter.ToInt32(recvData, 4);
            fx = System.BitConverter.ToInt32(recvData, 8);
            fy = System.BitConverter.ToInt32(recvData, 12);
            tx = System.BitConverter.ToInt32(recvData, 16);
            ty = System.BitConverter.ToInt32(recvData, 20);
            Quaternion q = new Quaternion(fx,fy,tx,ty);
            //Debug.Log(q);
            if (frameID != lastestFrame + 1)
            {
                Debug.Log("SyncError");
                //Sync Error
                return;
            }
            lastestFrame = frameID;
            Controller.Move(fx, fy, tx, ty);
            if (Controller.turn == Team.White)
            {
                Controller.turn = Team.Black;
                return;
            }
            if (Controller.turn == Team.Black)
            {
                Controller.turn = Team.White;
                return;
            }
        }

    }
    public void GameFinished()
    {
        UIPanels[2].SetActive(false);
        UIPanels[1].SetActive(true);
        MatchBtn.enabled = true;
        SendMove(-1,-1,-1,-1);
    }
    void OnApplicationQuit()
    {
        //SocketSend(quit);
        SocketQuit();
    }
}
