using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

public class NetworkClient : MonoBehaviour
{
    public enum ClientState
    {
        NONE,
        CONNECTING,
        GAME,
        END,
        DISCONNECT,
        CLEANUP
    }

    //game conncetivity
    public GroundPanel gameInterface;

    //UI connectivity
    public InputField IP;
    public InputField UserPort;
    public GameObject connectionPanel;


    //network config
    public string targetIP = "192.16.7.21";
    public int port = 8882;
    public ClientState state = ClientState.NONE;

    //UDP connection data
    protected int hostId;
    protected int connectionId;
    protected int ChannelId;
    protected int peerID;
    protected int peerChannel;

    public static void ConfigureConnection()
    {

    }

    public void Start()
    {
        gameInterface = GetComponent<GroundPanel>();
        NetworkTransport.Init();
        ConnectionConfig config = new ConnectionConfig();
        ChannelId = config.AddChannel(QosType.Reliable);
        HostTopology topology = new HostTopology(config, 2);
        hostId = NetworkTransport.AddHost(topology, port);
    }

    public void StartConnection()
    {
        Debug.Log("Connecting to: " + IP.text + " : " + int.Parse(UserPort.text));
        byte error;
        connectionId = NetworkTransport.Connect(hostId, IP.text, int.Parse(UserPort.text), 0, out error);
        state = ClientState.CONNECTING;
    }

    public void Update()
    {
        switch (state)
        {
            case ClientState.NONE:
                break;
            case ClientState.CONNECTING:
                ConnectionListen();
                break;
            case ClientState.GAME:
                Listen();
                UDPSend("STAT:0");
                break;
        }
    }


    public void ConnectionListen()
    {
        byte error;
        byte[] recBuffer = new byte[1024];
        int bufferSize = 1024;
        int dataSize;
        NetworkEventType recNetworkEvent = NetworkTransport.Receive(out peerID, out connectionId, out peerChannel, recBuffer, bufferSize, out dataSize, out error);
        switch (recNetworkEvent)
        {
            case NetworkEventType.ConnectEvent:
                Debug.Log("incoming connection event received");
                state = ClientState.GAME;
                connectionPanel.SetActive(false);
                gameInterface.MainUI.SetActive(true);
                gameInterface.gameStarted = true;
                break;
            default:
                break;
        }
    }

    public void Listen()
    {
        byte error;
        byte[] recBuffer = new byte[1024];
        int bufferSize = 1024;
        int dataSize;
        NetworkEventType recNetworkEvent = NetworkTransport.Receive(out peerID, out connectionId, out peerChannel, recBuffer, bufferSize, out dataSize, out error);
        switch (recNetworkEvent)
        {
            case NetworkEventType.DataEvent:
                Stream stream = new MemoryStream(recBuffer);
                BinaryFormatter formatter = new BinaryFormatter();
                string message = formatter.Deserialize(stream) as string;
                HandleData(message);
                break;
            case NetworkEventType.DisconnectEvent:
                Debug.Log("remote client event disconnected");
                break;
            default:
            case NetworkEventType.Nothing:
                break;
        }
    }

    public void HandleData(string data)
    {
        string[] tmpResp = data.Split(":"[0]);
        //Debug.Log("Client Got: " + data);
        switch (tmpResp[0])
        {
            case "STAT":
                //Debug.Log("Got TomData");
                gameInterface.SystemUpdate(float.Parse(tmpResp[1]), tmpResp[2], float.Parse(tmpResp[3]), tmpResp[4], float.Parse(tmpResp[5]), tmpResp[6], float.Parse(tmpResp[7]), tmpResp[8], float.Parse(tmpResp[9]), tmpResp[10], float.Parse(tmpResp[11]), tmpResp[12]);
                break;
        }
    }

    public void UDPSend(string outData)
    {
        byte error;
        byte[] buffer = new byte[1024];
        Stream streamData = new MemoryStream(buffer);
        BinaryFormatter formatterOut = new BinaryFormatter();
        formatterOut.Serialize(streamData, outData);
        int bufferSizeOut = 1024;
        NetworkTransport.Send(hostId, connectionId, ChannelId, buffer, bufferSizeOut, out error);
    }
}
