using System.Collections.Generic;
using System;
using UnityEngine;
using NeonTea.Quakeball.Interface;
using NeonTea.Quakeball.Networking.Instances;
using NeonTea.Quakeball.TeaNet.Peers;

namespace NeonTea.Quakeball.Networking {
    public class NetChaperone : MonoBehaviour, PeerMessageListener {

        public GameObject SpawnedRemotePlayer;

        private Terminal Terminal;

        private Queue<string> MessageQueue = new Queue<string>();

        public GameObject SpawnPlayer(Vector3 location) {
            GameObject obj = GameObject.Instantiate(SpawnedRemotePlayer);
            obj.transform.position = location;
            return obj;
        }

        private void Start() {
            if (Terminal.Singleton != null) {
                Terminal = Terminal.Singleton;
                Terminal.RegisterCommand("host", Host, "host [port] [address] - Hosts server at given address and port.");
                Terminal.RegisterCommand("join", Join, "join [address] [port] - Tries to join a server at given address and port.");
                Terminal.RegisterCommand("ping", Ping, "ping - return the current ping to any connection(s).");
                Terminal.RegisterCommand("disconnect", Disconnect, "disconnect - Stop current server, or close current client abruptly.");
            }
        }

        private void Update() {
            if (Net.Singleton.Instance != null) {
                Net.Singleton.Instance.Peer.Update();
                Net.Singleton.Instance.Update();
            }
            if (Terminal != null && Terminal.isActiveAndEnabled) {
                while (MessageQueue.Count > 0) {
                    Terminal.Println(MessageQueue.Dequeue());
                }
            }
        }

        private bool Host(string[] args) {
            if (args.Length > 2) {
                Terminal.Println($"<color={Terminal.ERROR_COLOR}>Can't accept more than 2 arguments.</color>");
                return false;
            }
            string addr = "0.0.0.0";
            string portstr = "8080";
            if (args.Length > 0) {
                portstr = args[0];
            }
            if (args.Length > 1) {
                addr = args[1];
            }
            int port;
            if (!Int32.TryParse(portstr, out port)) {
                return false;
            }
            Net.Singleton.StartServer(addr, port, this);
            return true;
        }

        private bool Join(string[] args) {
            if (args.Length > 2) {
                Terminal.Println($"<color={Terminal.ERROR_COLOR}>Can't accept more than 2 arguments.</color>");
                return false;
            }
            string addr = "127.0.0.1";
            string portstr = "8080";
            if (args.Length > 0) {
                addr = args[0];
            }
            if (args.Length > 1) {
                portstr = args[1];
            }
            int port;
            if (!Int32.TryParse(portstr, out port)) {
                return false;
            }
            Net.Singleton.StartClient(addr, port, this);
            return true;
        }

        private bool Ping(string[] args) {
            if (Net.Singleton.Instance == null) {
                Terminal.Println("No hosting or connecting has been done!");
                return false;
            }
            if (Net.Singleton.Instance is Client) {
                int ping = (int)(((Client)Net.Singleton.Instance).Ping * 1000);
                Terminal.Println($"Ping: {ping}ms");
            } else if (Net.Singleton.Instance is Server) {
                Server s = (Server)Net.Singleton.Instance;
                foreach (NetPlayer p in s.PlayerList) {
                    int ping = (int)(p.Ping * 1000);
                    Terminal.Println($"Ping for {p.Id}: {ping}ms");
                }
            }
            return true;
        }

        private bool Disconnect(string[] args) {
            if (Net.Singleton.Instance == null) {
                Terminal.Println("No hosting or connecting has been done!");
                return false;
            }
            Net.Singleton.Instance.Stop();
            return true;
        }

        public void Message(string msg) {
            MessageQueue.Enqueue(msg);
        }

        public void Err(string err) { }
    }
}
