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

public class NetworkHost : MonoBehaviour {

    public enum HostState
    {
        WAITING,
        CONNECTING,
        GAME,
        END,
        DISCONNECT,
        CLEANUP
    }

    //game conncetivity
    public TomPanel gameInterface;

    //UI control
    public GameObject connectionPanel;

    //network config
    public string targetIP = "192.16.7.21";
    public int port = 8881;
    public HostState state = HostState.WAITING;

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

    public void Start()
    {
        gameInterface = GetComponent<TomPanel>();
        NetworkTransport.Init();
        StartConnection();
    }


    public void StartConnection()
    {
        byte error;
        ConnectionConfig config = new ConnectionConfig();
        ChannelId = config.AddChannel(QosType.Reliable);
        HostTopology topology = new HostTopology(config, 2);
        hostId = NetworkTransport.AddHost(topology, port);
    }

    public void AbortConnection()
    {
        byte error;
        NetworkTransport.Disconnect(hostId, connectionId, out error);

    }

    public void Update()
    {
        switch (state)
        {
            case HostState.WAITING:
                ConnectionListen();
                break;
            case HostState.CONNECTING:
                Listen();
                break;
            case HostState.GAME:
                Listen();
                UDPSend("STAT:"+ gameInterface.systemHealth[(int)TomPanel.SystemType.Energy]+":"+ gameInterface.getError(TomPanel.SystemType.Energy) + ":"
                    + gameInterface.systemHealth[(int)TomPanel.SystemType.Life] + ":"+ gameInterface.getError(TomPanel.SystemType.Life) + ":"
                    + gameInterface.systemHealth[(int)TomPanel.SystemType.Water] + ":"+ gameInterface.getError(TomPanel.SystemType.Water) + ":"
                    + gameInterface.systemHealth[(int)TomPanel.SystemType.Communication] + ":"+ gameInterface.getError(TomPanel.SystemType.Communication) + ":"
                    + gameInterface.systemHealth[(int)TomPanel.SystemType.Navigation] + ":"+ gameInterface.getError(TomPanel.SystemType.Navigation) + ":"
                    + gameInterface.systemHealth[(int)TomPanel.SystemType.Computer] + ":"+ gameInterface.getError(TomPanel.SystemType.Computer));
                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 = HostState.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("Host Got: " + data);
        switch (tmpResp[0])
        {
            case "STAT":
                Debug.Log("Keep Alive");
                break;
            case "MSG":
                GetComponent<TomPanel>().mainText.text += "\n>>" + tmpResp[1];
                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);
    }
}
