using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Ionic.Utils.Zip;


namespace CensusParser
{

    public class PopulationAgeRange
    {
        public PopulationAgeRange() : this(0, 0, 0) { }

        public PopulationAgeRange(int pop, int start, int end)
        {
            Population = pop;
            StartRange = start;
            EndRange = end;
        }

        public int Population { get; set; }
        public int StartRange { get; set; }
        public int EndRange { get; set; }
    }

    public class Region
    {
        public Region()
        {
            popRanges = new List<PopulationAgeRange>();
        }

        public string Name { get; set; }
        public int TotalPopulation { get; set; }
        public int MalePopulation { get; set; }
        public int FemalePopulation { get; set; }

        private List<PopulationAgeRange> popRanges;

        public List<PopulationAgeRange> PopRanges
        {
            get { return popRanges; }
            set { popRanges = value; }
        }
    }

    public class State
    {
        public State()
        {
            regionsInState = new List<Region>();
        }

        private List<Region> regionsInState;

        public List<Region> RegionsInState
        {
            get { return regionsInState; }
            set { regionsInState = value; }
        }
    }

    public class CensusDemographicsParser
    {
        public static State ParseFile(string file)
        {
            State ret = new State();

            using (StreamReader sr = new StreamReader(file))
            {
                string line = String.Empty;

                bool firstLine = true;
                while ((line = sr.ReadLine()) != null)
                {
                    try
                    {
                        string[] lineParts = line.Split(',');

                        // Grab the parts of the line that we care about
                        Region r = new Region();

                        r.Name = RemoveQuotes(lineParts[14]);
                        
                        int index = 15;
                        if (firstLine)
                        {
                            index = 15;
                            firstLine = false;
                        }
                        else
                            index = 16;

                        r.TotalPopulation = Convert.ToInt32(lineParts[index++]);
                        r.MalePopulation = Convert.ToInt32(lineParts[index++]);
                        r.FemalePopulation = Convert.ToInt32(lineParts[index++]);

                        r.PopRanges.Add(new PopulationAgeRange(Convert.ToInt32(lineParts[index++]), 0, 4));
                        r.PopRanges.Add(new PopulationAgeRange(Convert.ToInt32(lineParts[index++]), 5, 9));
                        r.PopRanges.Add(new PopulationAgeRange(Convert.ToInt32(lineParts[index++]), 10, 14));
                        r.PopRanges.Add(new PopulationAgeRange(Convert.ToInt32(lineParts[index++]), 15, 19));
                        r.PopRanges.Add(new PopulationAgeRange(Convert.ToInt32(lineParts[index++]), 20, 24));
                        r.PopRanges.Add(new PopulationAgeRange(Convert.ToInt32(lineParts[index++]), 25, 34));
                        r.PopRanges.Add(new PopulationAgeRange(Convert.ToInt32(lineParts[index++]), 35, 44));
                        r.PopRanges.Add(new PopulationAgeRange(Convert.ToInt32(lineParts[index++]), 45, 54));
                        r.PopRanges.Add(new PopulationAgeRange(Convert.ToInt32(lineParts[index++]), 55, 59));
                        r.PopRanges.Add(new PopulationAgeRange(Convert.ToInt32(lineParts[index++]), 60, 64));
                        r.PopRanges.Add(new PopulationAgeRange(Convert.ToInt32(lineParts[index++]), 65, 74));
                        r.PopRanges.Add(new PopulationAgeRange(Convert.ToInt32(lineParts[index++]), 75, 84));
                        r.PopRanges.Add(new PopulationAgeRange(Convert.ToInt32(lineParts[index++]), 85, 200));

                        //  Add all the Ranges to the Region

                        ret.RegionsInState.Add(r);
                    }
                    catch (Exception e)
                    {
                        System.Diagnostics.Debug.WriteLine("Exception : " + e.Message);
                    }
                }

            }
            return ret;
        }

        private static string RemoveQuotes(string s)
        {
            StringBuilder result = new StringBuilder();

            foreach (char c in s)
            {
                if (c != '\"')
                    result.Append(c);
            }

            return result.ToString();
        }

        public static 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;

        }

    }
}