using System;
using System.Net;
using System.Net.Sockets;

using FilterAPI;
using FilterAPI.Networking;

namespace FilterZone.ZoneNetworking
{
    internal class ZoneClient : ClientMulti, IDisposable
    {
        public Guid ClientGUID = Guid.NewGuid();

        private FiestaCrypto CCrypto = null;
        private FiestaCrypto SCrypto = null;

        public String sID = String.Empty;

        public DateTime PremiumDateTime = DateTime.Now;

        public ZoneClient(Socket AcceptedSocket, IPEndPoint AcceptedEndPoint)
            : base(AcceptedSocket, AcceptedEndPoint, IPAddress.Parse(Program.Auth.ConfigValues[String.Format("Zone{0}ConnectIP", Program.ZoneID)]), Convert.ToInt32(Program.Auth.ConfigValues[String.Format("Zone{0}ConnectPort", Program.ZoneID)])) { }

        public void SendCrypto()
        {
            CCrypto = new FiestaCrypto(Program.Auth, 2);

            using (var ServerPacket = new Packet(2, 7))
            {
                ServerPacket.PacketWriter.Write((UInt16)2);

                SendPacketClient(ServerPacket);
            }
        }

        public override void ReceivedClient(Byte[] Buffer)
        {
            if (CCrypto != null) { CCrypto.Crypt(Buffer, 0, Buffer.Length); }

            using (var ClientPacket = new Packet(Buffer))
            {
                if (!ClientPacket.SetHeaderAndType()) { Dispose(); }
                else if (ClientPacket.Header == 6 && ClientPacket.Type == 1)
                {
                    UInt16 PlayerID = UInt16.MaxValue;

                    if (((PlayerID = ClientPacket.PacketReader.ReadUInt16()) != UInt16.MaxValue) && ((sID = ClientPacket.ReadString(16)) != String.Empty))
                    {
                        if (Program.SQL.sIDTaken(sID)) { SendPacketServer(ClientPacket); }
                    }
                }
                else if (ClientPacket.Header == 8 && ClientPacket.Type == 1)
                {
                    String Message = String.Empty;
                    
                    if ((Message = ClientPacket.PacketReader.ReadString()) != String.Empty)
                    {
                        Message = Message.Replace("?", "?");

                        Boolean SendMessage = true;

                        if (Convert.ToBoolean(Program.Auth.ConfigValues["ZoneFeatureNCBP"]))
                        {
                            Char InvalidSymbol;

                            if (Injection.ContainsInvalidSymbol(Message, out InvalidSymbol))
                            {
                                GlobalPacket.SendShoutMessageServer(this, "Server", "Please do not use \"{0}\" in your message.", InvalidSymbol);

                                SendMessage = false;
                            }
                        }

                        if (Convert.ToBoolean(Program.Auth.ConfigValues["ZoneFeatureNCL"]))
                        {
                            if (!Message.StartsWith("&")) { Program.SQL.InserttNormal(Program.ZoneID, sID, Message); }
                        }

                        if (SendMessage) { SendPacketServer(ClientPacket); }
                    }
                }
                else if (ClientPacket.Header == 8 && ClientPacket.Type == 30)
                {
                    String Message = String.Empty;

                    if ((Message = ClientPacket.PacketReader.ReadString()) != String.Empty)
                    {
                        Message = Message.Replace("?", "?");

                        Boolean SendMessage = true;

                        if (Convert.ToBoolean(Program.Auth.ConfigValues["ZoneFeatureSCBP"]))
                        {
                            Char InvalidSymbol;

                            if (Injection.ContainsInvalidSymbol(Message, out InvalidSymbol))
                            {
                                GlobalPacket.SendShoutMessageServer(this, "Server", "Please do not use \"{0}\" in your message.", InvalidSymbol);

                                SendMessage = false;
                            }
                        }

                        if (Convert.ToBoolean(Program.Auth.ConfigValues["ZoneFeatureSCL"])) { Program.SQL.InserttShout(Program.ZoneID, sID, Message); }

                        if (SendMessage) { SendPacketServer(ClientPacket); }
                    }
                }
                else if (ClientPacket.Header == 8 && ClientPacket.Type == 75)
                {
                    Int16 SlotID = -1;
                    Int16 MessageLenghth = -1;
                    String Message = String.Empty;

                    if ((SlotID = ClientPacket.PacketReader.ReadByte()) != -1 && (MessageLenghth = ClientPacket.PacketReader.ReadByte()) != -1 && (Message = ClientPacket.ReadString(MessageLenghth - 1)) != String.Empty)
                    {
                        Message = Message.Replace("?", "?");

                        Boolean SendMessage = true;

                        if (Convert.ToBoolean(Program.Auth.ConfigValues["ZoneFeatureRCBP"]))
                        {
                            Char InvalidSymbol;

                            if (Injection.ContainsInvalidSymbol(Message, true, out InvalidSymbol))
                            {
                                GlobalPacket.SendShoutMessageServer(this, "Server", "Please do not use \"{0}\" in your message.", InvalidSymbol);

                                SendMessage = false;
                            }
                        }

                        if (Convert.ToBoolean(Program.Auth.ConfigValues["ZoneFeatureRCL"])) { Program.SQL.InserttRoar(Program.ZoneID, sID, Message); }

                        if (SendMessage) { SendPacketServer(ClientPacket); }
                    }
                }
                else if (ClientPacket.Header == 12 && ClientPacket.Type == 32)
                {
                    if (PremiumDateTime > DateTime.Now)
                    {
                        TimeSpan PremiumSpan = PremiumDateTime - DateTime.Now;

                        if (PremiumSpan.TotalSeconds > 60)
                        {
                            Dispose();
                            
                            return;
                        }

                        PremiumDateTime = PremiumDateTime.AddSeconds(5);
                    }
                    else
                    {
                        PremiumDateTime = DateTime.Now.AddSeconds(5);

                        SendPacketServer(ClientPacket);
                    }
                }
                else { SendPacketServer(ClientPacket); }
            }
        }

        public void SendPacketClient(Packet ServerPacket)
        {
            Byte[] PacketBuffer;

            ServerPacket.ToArray(out PacketBuffer);

            SendClient(PacketBuffer);
        }

        public override void ReceivedServer(Byte[] Buffer)
        {
            using (var ServerPacket = new Packet(Buffer))
            {
                if (!ServerPacket.SetHeaderAndType()) { Dispose(); }
                else if (ServerPacket.Header == 2 && ServerPacket.Type == 7)
                {
                    SCrypto = new FiestaCrypto(Program.Auth, ServerPacket.PacketReader.ReadInt16(), false);

                    SendCrypto();
                }
                else if (ServerPacket.Header == 6 && ServerPacket.Type == 10)
                {
                    Byte[] Unk00 = ServerPacket.PacketReader.ReadBytes(10);
                    String IPAddress = ServerPacket.ReadString(16);
                    UInt16 Port = ServerPacket.PacketReader.ReadUInt16();
                    Byte[] Unk01 = ServerPacket.PacketReader.ReadBytes(2);

                    using (var ServerPacketRewrite = new Packet(6, 10))
                    {
                        ServerPacketRewrite.PacketWriter.Write(Unk00);
                        ServerPacketRewrite.WriteString(Program.Auth.ConfigValues["ZoneTransferIP"], 16);
                        ServerPacketRewrite.PacketWriter.Write(Port);
                        ServerPacketRewrite.PacketWriter.Write(Unk01);

                        SendPacketClient(ServerPacketRewrite);
                    }
                }
                else { SendPacketClient(ServerPacket); }
            }
        }

        public void SendPacketServer(Packet ClientPacket)
        {
            Byte[] PacketBuffer;

            ClientPacket.ToArray(SCrypto, out PacketBuffer);

            SendServer(PacketBuffer);
        }

        public override void Disconnected() { }
    }
}
