using System.IO;
using System.Threading.Tasks;

namespace Passer.Control {

    public static class SiteServer {
        public static async Task ReceiveData(Stream dataStream, Client client) {
            while (true) {
                byte packetSize = (byte)dataStream.ReadByte();
                if (packetSize == 0xFF)
                    //Debug.Log("Receive timeout");
                    // Timeout
                    ;
                else
                    await ReceiveData(dataStream, client, packetSize);
            }
        }

        public static async Task ReceiveData(Stream dataStream, Client client, byte packetSize) {
            byte msgId = (byte)dataStream.ReadByte();
            if (msgId == 0xFF) {
                // Timeout
                return;
            }

            bool result = false;
            switch (msgId) {
                case ClientMsg.Id: // 0xA0 / 160
                    result = await ClientMsg.Receive(dataStream, client, packetSize);
                    break;
                case NetworkIdMsg.Id: // 0xA1 / 161
                    result = await NetworkIdMsg.Receive(dataStream, client, packetSize);
                    break;
                case InvestigateMsg.Id: // 0x81
                    result = await InvestigateMsg.Receive(dataStream, client, packetSize);
                    break;
                case ThingMsg.Id: // 0x80 / 128
                    result = await ThingMsg.Receive(dataStream, client, packetSize);
                    break;
                case NameMsg.Id: // 0x91 / 145
                    result = await NameMsg.Receive(dataStream, client, packetSize);
                    break;
                case ModelUrlMsg.Id: // 0x90 / 144
                    result = await ModelUrlMsg.Receive(dataStream, client, packetSize);
                    break;
                case PoseMsg.Id: // 0x10 / 16
                    result = await PoseMsg.Receive(dataStream, client, packetSize);
                    break;
                case CustomMsg.Id: // 0xB1 / 177
                    result = await CustomMsg.Receive(dataStream, client, packetSize);
                    break;
                case TextMsg.Id: // 0xB0 / 176
                    result = await TextMsg.Receive(dataStream, client, packetSize);
                    break;
                case DestroyMsg.Id: // 0x20 / 32
                    result = await DestroyMsg.Receive(dataStream, client, packetSize);
                    break;
                default:
                    break;
            }
            if (result == false) {
                packetSize = msgId; // skip 1 byte, msgId is possibly a packet size byte
                await ReceiveData(dataStream, client, packetSize);
            }
        }

        //public static void ProcessMessage(ISiteServer site, Client client, IMessage msg) {
        //    client.ProcessMessage(site, client, msg);
        //    switch (msg) {
        //        case ClientMsg clientMsg:
        //            site.ProcessClient(client, clientMsg);
        //            break;
        //        case NetworkIdMsg networkId:
        //            site.ProcessNetworkId(client, networkId);
        //            break;
        //        case InvestigateMsg investigate:
        //            site.ProcessInvestigate(client, investigate);
        //            break;
        //        case ThingMsg thing:
        //            site.ProcessThing(client, thing);
        //            break;
        //        case NameMsg name:
        //            site.ProcessName(client, name);
        //            break;
        //        case ModelUrlMsg modelUrl:
        //            site.ProcessModelUrl(client, modelUrl);
        //            break;
        //        case PoseMsg pose:
        //            site.ProcessPose(client, pose);
        //            break;
        //        case CustomMsg custom:
        //            site.ProcessCustom(client, custom);
        //            break;
        //        case TextMsg text:
        //            site.ProcessText(client, text);
        //            break;
        //        case DestroyMsg destroy:
        //            site.ProcessDestroy(client, destroy);
        //            break;
        //    }
        //}
    }

    //public interface ISiteServer {

    //    public void ProcessClient(Client client, ClientMsg clientMsg);
    //    public void ProcessNetworkId(Client client, NetworkIdMsg networkId);
    //    public void ProcessInvestigate(Client client, InvestigateMsg investigate);
    //    public void ProcessThing(Client client, ThingMsg thing);
    //    public void ProcessName(Client client, NameMsg name);
    //    public void ProcessModelUrl(Client client, ModelUrlMsg modelUrl);
    //    public void ProcessPose(Client client, PoseMsg pose);
    //    public void ProcessCustom(Client client, CustomMsg custom);
    //    public void ProcessText(Client client, TextMsg text);
    //    public void ProcessDestroy(Client client, DestroyMsg destroy);
    //}
}