using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using CensusParser;

namespace Processor
{
    public partial class Processor : Form
    {
        private string accessKey = "Enter your AWS Key here";
        private string secretKey = "Enter your AWS Private Key here";

        private string datasetDrive = @"F:";
        private string parseQueue = "CensusParseQueue";

        private SQS.Worker processorWorker = new SQS.Worker();

        public Processor()
        {
            InitializeComponent();

            btnStart.Enabled = true;
            btnStop.Enabled = false;

            processorWorker.AwsID = accessKey;
            processorWorker.AWSSecretKey = secretKey;
            processorWorker.Queue = parseQueue;
            processorWorker.PollingMode = SQS.SQSManager.pollMode.Adaptive;
            processorWorker.Threads = 1;
            processorWorker.ReceiveDelay = 100;
            processorWorker.requestEvent += new SQS.Worker.ProcessEvent(processorWorker_requestEvent);
            processorWorker.MeasureNetLatency = false;

            lbOutput.Items.Add("Initialization Done");
        }

        LinkedList<CensusParser.Region> topTen = new LinkedList<CensusParser.Region>();

        bool processorWorker_requestEvent(SQS.Worker worker, SQS.SQSMessage message)
        {
            topTen.Clear();

            lbOutput.Items.Add("Received message : " + Convert.ToString(DateTime.Now) + " - "+ message._payload);
            Debug.WriteLine(" Message : " + message._payload);

            State censusRegion = CensusDemographicsParser.UnzipCensusDataAndParse(message._payload);
            
            int lowestValue = 0;

            string censusRegionName = censusRegion.RegionsInState[0].Name;

            // Go through each of the regions in the censusRegion
            // and figure out if we need to add that to the topTen
            foreach (CensusParser.Region r in censusRegion.RegionsInState)
            {
                int currVal = r.PopRanges[4].Population + r.PopRanges[5].Population;

                Debug.WriteLine(" lowestValue = " + lowestValue + " : currVal = " + currVal + " : t10.Count = " + topTen.Count);

                if (!r.Name.Equals(censusRegionName) &&
                    !r.Name.Contains("District"))
                {
                    if (topTen.Count < 10)
                    {
                        if ((currVal > lowestValue) || (lowestValue == 0))
                        {
                            lowestValue = InsertSortedToTopTen(r, currVal, lowestValue);
                        }
                    }
                    else if (currVal > lowestValue)
                    {
                        // Insert somewhere inside the list
                        lowestValue = InsertSortedToTopTen(r, currVal, lowestValue);
                    }
                }
            }

            StringBuilder topTenString = new StringBuilder();

            Debug.WriteLine(" === " + censusRegionName);
            foreach (CensusParser.Region r in topTen)
            {
                int regVal = r.PopRanges[4].Population + r.PopRanges[5].Population;

                topTenString.Append(censusRegionName+"|"+r.Name + "|" + Convert.ToString(regVal) + ",");
                 
                Debug.WriteLine(" Region : " + r.Name + " Pop 20-34 : " + Convert.ToString(regVal));
            }
            Debug.WriteLine("");

            worker.PutResponse(message, topTenString.ToString());

            lbOutput.Items.Add("PutResponse Complete ");

            return true;
        }

        private int InsertSortedToTopTen(CensusParser.Region r, int currVal, int lowestValue)
        {
            Debug.WriteLine("Adding : " + r.Name);

            if ((topTen.Count == 0) || (topTen.Count == 1))
                topTen.AddFirst(r);
            else
            {
                LinkedListNode<CensusParser.Region> currNode = topTen.First;

                int currNodeVal = 0;
                bool inserted = false;

                while (!inserted)
                {

                    CensusParser.Region currNodeRegion = currNode.Value;
                    currNodeVal = currNodeRegion.PopRanges[4].Population +
                            currNodeRegion.PopRanges[5].Population;

                    // If the currVal is bigger than the current node
                    if (currVal > currNodeVal)
                    {
                        Debug.WriteLine("Adding Before : " + currNode.Value.Name);
                        topTen.AddBefore(currNode, r);
                        inserted = true;
                    }
                    else
                    {
                        if (currNode == topTen.Last)
                        {
                            Debug.WriteLine("Adding After : " + currNode.Value.Name);
                            topTen.AddAfter(currNode, r);
                            inserted = true;
                        }
                        else
                            currNode = currNode.Next;
                    }
                }
                
                // If we went over 10 nodes, remove the last node
                if (topTen.Count > 10)
                {
                    topTen.RemoveLast();
                }
            }

            int newLowest = topTen.Last.Value.PopRanges[4].Population +
                topTen.Last.Value.PopRanges[5].Population;

            return newLowest;
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            btnStart.Enabled = false;
            btnStop.Enabled = true;

            lbOutput.Items.Clear();

            processorWorker.Start();
            lbOutput.Items.Add("SQS Started at " + Convert.ToString(DateTime.Now));


        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            btnStart.Enabled = true;
            btnStop.Enabled = false;

            processorWorker.Stop();
            lbOutput.Items.Add("SQS Stopped at " + Convert.ToString(DateTime.Now));
        }

        void Form1_FormClosed(object sender, System.Windows.Forms.FormClosedEventArgs e)
        {
            processorWorker.Stop();
        }
    }
}
