using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using Microsoft.Office.Interop.Excel;
using Microsoft.Office.Tools.Excel;
using Microsoft.Office.Tools.Excel.Extensions;
using Ionic.Utils.Zip;
using CensusParser;
using Amazon.SimpleDB;
using CensusDB;
using ExcelLib;

namespace CensusExcelViewer
{
    public partial class CensusViewerUserControl : UserControl
    {
        public CensusViewerUserControl()
        {
            InitializeComponent();
            
            grpAWS.Visible = false;
            grpRegion.Visible = false;
            grpPDSConfig.Visible = false;
        }

        private void btnLoadPDS_Click(object sender, EventArgs e)
        {
            string formatMessage = "Invalid drive letter for PDS.  The drive letter must be in the following format '<drive letter>:'";
            string pdsInvalidDrive = "The drive you pointed at does not contain the Year 2000 Census Public Data Set.";
            // Check the format of the drive letter
            if (txtCensusDrive.Text.Length != 2)
            {
                MessageBox.Show(formatMessage);
            }
            else if (txtCensusDrive.Text[1] != ':')
            {
                MessageBox.Show(formatMessage);
            }
            else
            {
                // Go through all directories to enumerate the regions and fill
                // the regions listbox.
                StringBuilder regionsPath = new StringBuilder();
                regionsPath.Append(txtCensusDrive.Text);
                regionsPath.Append(@"/census_2000/datasets/demographic_profile");

                string dirpath = regionsPath.ToString();

                DirectoryInfo regionsDI = new DirectoryInfo(dirpath);

                if (regionsDI.Exists == false)
                {
                    MessageBox.Show(pdsInvalidDrive);
                }
                else
                {

                    DirectoryInfo[] dirs = regionsDI.GetDirectories();

                    regions = new Dictionary<string, string>();
                    regions.Clear();

                    lbRegions.Items.Clear();
                    foreach (DirectoryInfo d in dirs)
                    {
                        string formattedRegion = FormatDirs(d.Name);
                        
                        // Save the name to the dictionary.  We'll use it later
                        // to parse the data
                        regions.Add(formattedRegion, d.FullName);

                        lbRegions.Items.Add(formattedRegion);
                    }

                    grpRegion.Visible = true;
                }
            }

        }

        private Dictionary<string, string> regions;

        private string FormatDirs(string s)
        {
            string ret = string.Empty;
            
            // Remove the 0_ from those Regions that start with it
            if (s.IndexOf("0_") == 0)
            {
                s = s.Substring(2);
            }

            s = s.Replace('_', ' ');

            ret = s;

            return s;
        }

        private State UnzipCensusDataAndParse(string selPath)
        {
            // Initialize the return object
            State state = new State();

            string dataPathandFile = string.Empty;

            // find the zip file in the directory
            DirectoryInfo di = new DirectoryInfo(selPath);
            FileInfo[] fi = di.GetFiles();

            foreach (FileInfo f in fi)
            {
                if (f.Name.Contains(".zip"))
                {
                    // Figure out if we've already unzipped this file into a directory
                    int zipPos = f.Name.IndexOf(".zip");
                    string zipDirName = f.Name.Substring(0, zipPos);

                    DirectoryInfo[] zipDirInfo = di.GetDirectories();
                    bool bDirExist = false;

                    foreach (DirectoryInfo d in zipDirInfo)
                    {
                        if (d.Name == zipDirName)
                        {
                            // We found an existing dir
                            bDirExist = true;

                            dataPathandFile = d.FullName + "\\" + zipDirName + ".csv";
                            break;
                        }
                    }

                    if (bDirExist == false)
                    {
                        // Create the directory
                        DirectoryInfo newZipDir = di.CreateSubdirectory(zipDirName);

                        dataPathandFile = newZipDir.FullName + "\\" + zipDirName + ".csv";

                        // Unzip the file
                        using (ZipFile zip = ZipFile.Read(f.FullName))
                        {
                            zip.ExtractAll(newZipDir.FullName, true);
                        }
                    }

                    // Parse the file into objects
                    state = CensusDemographicsParser.ParseFile(dataPathandFile);

                    break;
                }
            }

            return state;

        }

        private void btnCreateWS_Click(object sender, EventArgs e)
        {
            // Figure out the currently selected item
            if ((string)lbRegions.SelectedItem == null)
            {
                MessageBox.Show("Please select a region to create a Worksheet with PDS data.");
            }
            else
            {

                State censusRegion = null;
                string selRegion = (string)lbRegions.SelectedItem;

                // Handle the case where we're pulling directly 
                // from the PDS Volume
                if (bFromPDSVolume == true)
                {
                    string selPath = regions[selRegion];

                    censusRegion = UnzipCensusDataAndParse(selPath);
                }

                // Handle the case when we have Census Data in 
                // SimpleDB
                if (bFromSimpleDB == true)
                {
                    CensusSimpleDB csdb = new CensusSimpleDB(service);

                    censusRegion = csdb.GetCensusRegionFromSimpleDB(selRegion, simpleDBDomain);
                }

                ExcelHelper eh = new ExcelHelper(Globals.ThisAddIn.Application);
                eh.AddSheet(censusRegion.RegionsInState[0].Name);

                eh.SetCell("A", "1", censusRegion.RegionsInState[0].Name);

                // Set Column Titles
                eh.SetCell("A", "3", "Region");
                eh.SetCell("B", "3", "Total Population");
                eh.SetCell("C", "3", "Females");
                eh.SetCell("D", "3", "Males");

                char currCol = 'E';

                foreach (PopulationAgeRange pop in censusRegion.RegionsInState[0].PopRanges)
                {
                    eh.SetCell(Convert.ToString(currCol), "3", Convert.ToString(pop.StartRange) + " to "+Convert.ToString(pop.EndRange));
                    currCol++;
                }

                int row = 4;
                foreach (CensusParser.Region r in censusRegion.RegionsInState)
                {
                    eh.SetCell("A", Convert.ToString(row), r.Name);
                    eh.SetCell("B", Convert.ToString(row), Convert.ToString(r.TotalPopulation));
                    eh.SetCell("C", Convert.ToString(row), Convert.ToString(r.FemalePopulation));
                    eh.SetCell("D", Convert.ToString(row), Convert.ToString(r.MalePopulation));
                    char currCol2 = 'E';

                    foreach (PopulationAgeRange pop in r.PopRanges)
                    {
                        eh.SetCell(Convert.ToString(currCol2), Convert.ToString(row), Convert.ToString(pop.Population));
                        currCol2++;
                    }

                    row++;
                }
            }
        }

        private bool bFromPDSVolume = false;
        private bool bFromSimpleDB = false;

        private void btnFromPDSVolume_Click(object sender, EventArgs e)
        {
            grpPDSConfig.Location = new System.Drawing.Point(6,151);
            grpRegion.Location = new System.Drawing.Point(6,226);

            grpPDSConfig.Visible = true;
            grpRegion.Visible = false;
            grpAWS.Visible = false;

            bFromPDSVolume = true;
            bFromSimpleDB = false;

        }

        private void btnFromSimpleDB_Click(object sender, EventArgs e)
        {
            grpAWS.Location = new System.Drawing.Point(6,151);
            grpRegion.Location = new System.Drawing.Point(6,254);

            grpPDSConfig.Visible = false;
            grpRegion.Visible = false;
            grpAWS.Visible = true;

            bFromSimpleDB = true;
            bFromPDSVolume = false;
        }

        private static AmazonSimpleDB service;
        private static string simpleDBDomain = "CensusDomain";
        private static string accessKeyId = "Enter your AWS Key here";
        private static string secretAccessKey = "Enter your AWS Private Key here";


        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnConfigure_Click(object sender, EventArgs e)
        {
            // Get the Regions from SimpleDB 
            // TODO (12/29/2008): Use the keys from the UI!
            service = new AmazonSimpleDBClient(accessKeyId, secretAccessKey);

            CensusSimpleDB csdb = new CensusSimpleDB(service);

            if (!csdb.DoesSimpleDBDomainExist(simpleDBDomain))
            {
                MessageBox.Show("The SimpleDB Domain does not exist.  Use the SimpleCensusToSimpleDB application to populate SimpleDB.");
            }
            else
            {
                List<string> regions = csdb.GetCensusRegions(simpleDBDomain);

                // Fill in lbRegions
                lbRegions.Items.Clear();

                foreach (string region in regions)
                {
                    lbRegions.Items.Add(region);
                }

                // Make the lbRegions visible
                grpRegion.Visible = true;
            }
        }

    }
}
