using System;
using System.Net;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.Collections.Generic;

using FilterAPI.External;
using FilterAPI.Networking;
using FilterAPI.CustomCurrency;

namespace FilterPayment.PaymentNetworking
{
    internal class PaymentClient : IDisposable
    {
        private Socket ClientSocket;
        private IPEndPoint ClientEndPoint;

        private Byte[] ClientBuffer;

        private Int32 IsConnected;

        public PaymentClient(Socket AcceptedSocket, IPEndPoint AcceptedEndPoint)
        {
            ClientSocket = AcceptedSocket;
            ClientEndPoint = AcceptedEndPoint;

            ClientBuffer = new Byte[1024];

            try { ClientSocket.BeginReceive(ClientBuffer, 0, ClientBuffer.Length, SocketFlags.None, new AsyncCallback(PaymentReceived), null); }
            catch { Disconnect(); }
        }

        private void PaymentReceived(IAsyncResult Result)
        {
            if (IsConnected != 0) { return; }

            Int32 ReceivedLength = 0;

            try { ReceivedLength = ClientSocket.EndReceive(Result); }
            catch
            {
                Disconnect();

                return;
            }

            if (ReceivedLength >= 1)
            {
                Array.Resize(ref ClientBuffer, ReceivedLength);
                
                String HTTPRequest = Encoding.ASCII.GetString(ClientBuffer).Split(new String[] { " HTTP/1.1" }, StringSplitOptions.None)[0].Replace("GET /", "").Replace("?", "").Split('\n')[0];

                String[] HTTPRequestSplit = HTTPRequest.Split('&');

                Dictionary<String, String> HTTPParameters = new Dictionary<String, String>();

                foreach (String HTTPParameter in HTTPRequestSplit)
                {
                    try { HTTPParameters.Add(HTTPParameter.Split('=')[0], HTTPParameter.Split('=')[1]); }
                    catch { }
                }

                String IP = Convert.ToString(ClientEndPoint.Address);

                if ((IP == "54.85.0.76" || IP == "54.84.205.80" || IP == "54.84.27.163") && HTTPParameters.ContainsKey("id") && HTTPParameters.ContainsKey("new") && HTTPParameters.ContainsKey("total") && HTTPParameters.ContainsKey("oid") && HTTPParameters.ContainsKey("sig") && HTTPParameters.ContainsKey("uid"))
                {
                    Int64 ID = Convert.ToInt64(HTTPParameters["id"]);
                    Int64 New = Convert.ToInt64(HTTPParameters["new"]);
                    Int64 Total = Convert.ToInt64(HTTPParameters["total"]);
                    Int64 OID = Convert.ToInt64(HTTPParameters["oid"]);
                    String Sig = Convert.ToString(HTTPParameters["sig"]);
                    Int32 UID = Convert.ToInt32(HTTPParameters["uid"]);

                    String CompareSig = MD5String.CreateMD5(String.Format("{0}:{1}:{2}:{3}", ID, New, UID, Program.Auth.ConfigValues["SuperRewardsASK"]), "x2");

                    if (Sig != CompareSig)
                    {
                        Program.SendConsoleText(ConsoleColor.Red, "Invalid signature receieved from superrewards. SR sig: {0}. Filter sig: {1}.", Sig, CompareSig);

                        SendResponse("0\n");
                    }
                    else
                    {
                        if (!Program.SQL.nEMIDExists(UID))
                        {
                            Program.SendConsoleText(ConsoleColor.Red, "Superrewards sent payment for {0} ({1}) but could not find the account.", UID, ID);

                            SendResponse("0\n");
                        }
                        else
                        {
                            if (Program.SQL.nIDExists(ID))
                            {
                                Program.SendConsoleText(ConsoleColor.Red, "Superrewards sent transaction twice. Transaction ID: {0}.", ID);

                                SendResponse("0\n");
                            }
                            else
                            {
                                Currency MallCurrency = Program.Currencies.Currencies.Where(CurrencyID => CurrencyID.CurrencyID == Convert.ToByte(Program.Auth.ConfigValues["PaymentMCID"])).FirstOrDefault();

                                Program.SQL.AddAmountForCC(MallCurrency.TableName, New, "nUserNo", UID);
                                Program.SQL.InserttSRPayment(ID, New, Total, OID, Sig, UID);

                                SendResponse("1\n");

                                Program.SendConsoleText(ConsoleColor.Green, "Received payment from {0} ({1}). Transaction ID: {2}.", Program.SQL.GetsUsernameFromnEMID(UID), UID, ID);

                                if (Convert.ToBoolean(Program.Auth.ConfigValues["PaymentFeatureAP"]))
                                {
                                    String OnlinesID = String.Empty;

                                    foreach (String sID in Program.SQL.GetsIDsFornUserNo(UID))
                                    {
                                        if (Program.SQL.GettLoggedInChar(sID)) { OnlinesID = sID; }
                                    }

                                    if (OnlinesID != String.Empty)
                                    {
                                        using (var LocalPacket = new Packet(4, 8))
                                        {
                                            LocalPacket.PacketWriter.Write((Byte)1);
                                            LocalPacket.PacketWriter.Write("");
                                            LocalPacket.PacketWriter.Write(String.Format("Thank you {0} for donating to {1}.", OnlinesID, Program.Auth.ConfigValues["ServerName"]));

                                            Program.LocalClient.SendPacket(LocalPacket);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                //else if ((IP == "174.36.92.186" || IP == "174.36.92.187" || IP == "174.36.92.192" || IP == "174.36.96.66" || IP == "174.37.14.28"))
                //{
                //    Int32 UID = Convert.ToInt32(HTTPParameters["uid"]);
                //    Int32 GoodsID = Convert.ToInt32(HTTPParameters["goodsid"]);
                //    Int32 SLength = Convert.ToInt32(HTTPParameters["slength"]);
                //    Int32 SPeriod = Convert.ToInt32(HTTPParameters["speriod"]);
                //    Int32 Type = Convert.ToInt32(HTTPParameters["type"]);
                //    Int32 Ref = Convert.ToInt32(HTTPParameters["ref"]);
                //    Boolean IsTest = Convert.ToBoolean(HTTPParameters["is_test"]);
                //    String Sig = HTTPParameters["sig"];

                //    String CompareSig = MD5String.CreateMD5(String.Format("uid={0}goodsid={1}slength={2}speriod={3}type={4}ref={5}{6}", UID, GoodsID, SLength, SPeriod, Type, Ref, Program.Auth.ConfigValues["PaymentWallS"]), "x2");
                //    if (Sig != CompareSig) { Program.SendConsoleText(ConsoleColor.Red, "Invalid signature receieved from paymentwall. PW sig: {0}. Filter sig: {1}.", Sig, CompareSig); }
                //    else
                //    {
                //        if (Program.SQL.nIDExists(UID)) { Program.SendConsoleText(ConsoleColor.Red, "Superrewards sent transaction twice. Transaction ID: {0}.", UID); }
                //        else
                //        {
                //            if (Type == 0)
                //            {
                //                Currency MallCurrency = Program.Currencies.Currencies.Where(CurrencyID => CurrencyID.CurrencyID == Convert.ToByte(Program.Auth.ConfigValues["PaymentMCID"])).FirstOrDefault();

                //                Program.SQL.AddAmountForCC(MallCurrency.TableName, New, "nUserNo", UID);

                //                SendResponse("OK");
                //            }
                //            else if (Type == 2)
                //            {
                //                //charge back
                //            }
                //        }
                //    }
                //}
                else { Program.SendConsoleText(ConsoleColor.Blue, "Unknown request sent to payment system\n{0}", HTTPRequest); }

                Disconnect();
            }
            else { Disconnect(); }
        }

        private void SendResponse(String Text)
        {
            String ResponseData = String.Empty;

            ResponseData = String.Concat(ResponseData, "HTTP/1.1 200 OK", Environment.NewLine);
            ResponseData = String.Concat(ResponseData, "Date: ", String.Format("{0:r}", DateTime.Now), Environment.NewLine);
            ResponseData = String.Concat(ResponseData, "Server: Kobalts Web Server.", Environment.NewLine);
            ResponseData = String.Concat(ResponseData, "Content-Length: ", Text.Length, Environment.NewLine);
            ResponseData = String.Concat(ResponseData, "Content-Type: text/html", Environment.NewLine);
            ResponseData = String.Concat(ResponseData, Environment.NewLine);
            ResponseData = String.Concat(ResponseData, Text);

            ClientSocket.Send(Encoding.ASCII.GetBytes(ResponseData));
        }

        private void Disconnect()
        {
            if (IsConnected == 0 && Interlocked.CompareExchange(ref IsConnected, 1, 0) == 0)
            {
                try { ClientSocket.Dispose(); }
                catch { }

                ClientEndPoint = null;

                ClientBuffer = new Byte[0];
            }
        }

        ~PaymentClient() { Dispose(); }

        public void Dispose() { Disconnect(); }
    }
}
