using System;
using System.Collections.Generic;
using System.Collections;
using System.IO;    // potrebne pre natiahnutie XML z ineho ako xap zdroja
using System.IO.IsolatedStorage;
using System.Linq;  // potrebne pre natiahnutie XML z ineho ako xap zdroja
using System.Net;   // potrebne pre natiahnutie XML z ineho ako xap zdroja
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Resources; // pre rpacu so zip
using System.Xml.Linq;


namespace GraphicChart.Core
{
    public class XmlParsing
    {

        private Grid gr;                                // hlavny grid kde sa budu vykrelsovat grafy
        private List<string> s1;                        // tu je ulozeny list stringov pre selekciu, teda ak sa kliklo na nejekay obdlznik
        private List<List<string>> data;                // datovy zdroj grafu
        private List<string> sort;                      // tu je ulozeny list stringov pre selekciu ak sa sortovalo "1a" graf 1 ascending
        private List<List<string>> rows;                // premenne do ktorych sa budu ukladat datove zlozky vytvoria 2D pole
        private string sXML;                            // premena v ktorej je nazov ZIP suboru ak je k diposzicii zip archiv
        private IEnumerable<Core.ChartVariables> ess;   // uplne vsekty premmne pre vsekty grafy
        private string saveLoad;                        // nastavuje ci sa uklada alebo save-uje
        private string granularity;                     // string pre Granularitu "month",...
        private List<string> alternativeList;           // list alternativnych grafov
       
        /// <summary>
        /// Metoda, pomocou ktorej sa naplnia nastavenia pre vsetky grafy, ktore su definovane v "data.xml"
        /// </summary>
        public XmlParsing(Grid layoutRoot, List<string> s2, List<string> sort1, List<List<string>> data1, IEnumerable<Core.ChartVariables> es1)
        {
            // vytvorim si kolekciu kolekci, nieco ako 2D pole stringov, ale moze to byt pootm hocico
            rows = new List<List<string>>();
            gr = layoutRoot; 
            ess = es1;
            data = data1;
            s1 = s2;
            sort = sort1;
            sXML = "";
            saveLoad = "";
            granularity = "month";
            alternativeList = new List<string>();          
            ReadFromXML();
        }

        /// <summary>
        /// Metoda, pomocou ktorej sa naplnia nastavenia pre vsetky grafy, ktore su definovane v "data.xml"
        /// </summary>
        public XmlParsing(Grid layoutRoot, List<string> s2, List<string> sort1, List<List<string>> data1, IEnumerable<Core.ChartVariables> es1, string granularity1, List<string> alternativeList1)
        {
            // vytvorim si kolekciu kolekci, nieco ako 2D pole stringov, ale moze to byt pootm hocico
            rows = new List<List<string>>();
            gr = layoutRoot;
            ess = es1;
            data = data1;
            s1 = s2;
            sort = sort1;
            sXML = "";
            saveLoad = ""; 
            granularity = granularity1;
            alternativeList = alternativeList1;           
            ReadFromXML();            
        }

        /// <summary>
        /// Metoda, pomocou ktorej sa naplnia nastavenia pre vsetky grafy, ktore su definovane v "data.xml"
        /// </summary>
        public XmlParsing(Grid layoutRoot, string saveLoad1)
        {
            rows = new List<List<string>>();
            gr = layoutRoot;
            ess = null;
            data = null;
            s1 = new List<string>(); ;
            sort = new List<string>();
            sXML = "";
            saveLoad = saveLoad1;
            granularity = "month";
            alternativeList = new List<string>();   
            ReadFromXML();
        }

        /// <summary>
        /// Nacitanie dat z XML suboru
        /// </summary>
        private void ReadFromXML(){
            // ak uz bola stranka niekedy nacitana tak netreba znova stahovat datovy subor
            if (data != null & ess != null)
            {
                foreach (ChartVariables tr in ess)
                {

                    tr.Granularity = granularity;
                    tr.AlternativeList = alternativeList;

                    // inicializuje graf podla typu aky sa ma vykreslit
                    switch (tr.ChartType)
                    {
                        // vykresli klasicky stlpcovy 2D graf
                        case "ColumnChart2D":
                            ColumnCharts.ColumnChart2D chart = new ColumnCharts.ColumnChart2D(sort, s1, gr, tr, data, ess);
                            break;
                        // vykresli klasicky kolacovy 2D graf
                        case "PieChart2D":
                            PieChart.PieChart2D pieChart2D = new PieChart.PieChart2D(sort, s1, gr, tr, data, ess);
                            break;
                    }
                } 
            }
            else
            {
                WebClient wc = new WebClient();

                // vitiahne cestu k XMLku zo spanu
                string pathToXML = App.Current.Resources["xmlSource"].ToString();
                // ak naslo miesot xml zip archiv tak odtial vytiehne nazov archivu
                if (pathToXML.ToString().IndexOf("zip") != -1)
                {
                    sXML = pathToXML.ToString().Substring(pathToXML.ToString().LastIndexOf('/') + 1, pathToXML.ToString().LastIndexOf('.') - pathToXML.ToString().LastIndexOf('/') - 1);
                    sXML += ".xml";
                }
                wc.OpenReadCompleted += wc_OpenReadCompleted;
                wc.OpenReadAsync(new Uri(pathToXML));
            }        
        }

        
        /// <summary>
        /// Co sa ma stat po natiahnuti XML suboru, pripadne natiahnutiu tohto suboru zo zip archivu
        /// spracuvava sa tu kompletne XML vytvoria sa premenne pre graf a nainicializuju sa grafy
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
        {
            // pomocny string, ktory vytvara specificke meno xml suboru podla ulozeneho xml suboru
            string uriString = App.Current.Resources["xmlSource"].ToString();
            uriString = uriString.Replace('/', 'x'); uriString = uriString.Replace(':', 'x');
            uriString = uriString.Replace('\\', 'x'); uriString = uriString.Replace('&', 'x');
            uriString = uriString.Replace('?', 'x'); uriString = uriString.Replace('\'', 'x');
            uriString = uriString.Replace('"', 'x'); uriString = uriString.Replace('.', 'x');
            string xmlName = uriString + "data.xml";
            string txtDatetimeName = uriString + "streamdatetime.txt";

            if (e.Error != null)
            {
                return;
            }
            using (Stream s = e.Result)
            {

                XDocument ThisDoc = new XDocument();

                // ak je datovy zdroj ZIP archiv
                if (sXML != "")
                {
                    StreamResourceInfo zipResourceInfo = new StreamResourceInfo(s, @"application/zip");
                    StreamResourceInfo xmlResourceInfo = Application.GetResourceStream(zipResourceInfo, new Uri(sXML, UriKind.Relative));
                    ThisDoc = XDocument.Load(xmlResourceInfo.Stream);
                }
                else
                {
                    ThisDoc = XDocument.Load(s);
                }

                // ak nastane SAVE
                if (saveLoad == "s")
                {
                    using (IsolatedStorageFile store = 
                    IsolatedStorageFile.GetUserStoreForApplication())
                    {
                        IsolatedStorageFileStream stream = 
                            store.OpenFile(xmlName, FileMode.Create, FileAccess.Write);
                        ThisDoc.Save(stream);
                        stream.Dispose();
                        MessageBox.Show("Grafy úspešne uložené");
                        // datum ulozenia suboru
                        IsolatedStorageFileStream streamDateTime = 
                            store.CreateFile(txtDatetimeName);
                        StreamWriter writer = new StreamWriter(streamDateTime);
                        writer.Write(DateTime.Now);
                        writer.Close();
                    }              
                }else{

                    // ak nastane LOAD
                    if (saveLoad == "l")
                    {
                        try
                        {
                            using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
                            {
                                IsolatedStorageFileStream stream = store.OpenFile(xmlName, FileMode.Open, FileAccess.Read);
                                StreamReader reader = new StreamReader(stream);
                                ThisDoc = XDocument.Load(reader);
                                reader.Dispose();
                                stream.Dispose();
                            }
                            using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
                            {
                                IsolatedStorageFileStream stream = store.OpenFile(txtDatetimeName, FileMode.Open);
                                StreamReader reader = new StreamReader(stream);
                                string stemp = reader.ReadLine();
                                reader.Close();
                                MessageBox.Show("Načítavam grafy zo dňa: " + stemp);
                            }
                        }
                        catch (Exception err)
                        {
                            MessageBox.Show("Žiadne uložené grafy");
                        }

                    }

                    List<ChartVariables> chartVariables;
                    chartVariables = new List<ChartVariables>();


                    // vytiahnutie tych dat, ktore potrebujem z XML a ich priradenie k "ChartVariables"
                    // konkretne datova zlozka
                    var es1 = from b
                             in ThisDoc.Descendants("row")
                              select b;

                    foreach (var row in es1)
                    {
                        List<string> cells = new List<string>();

                        IEnumerable<XElement> clm;
                        clm = row.Elements("column");

                        foreach (var rl in clm)
                        {
                            cells.Add(rl.Value);
                        }
                        rows.Add(cells);
                    }

                    // vytiahnutie tych dat, ktore potrebujem z XML a ich priradenie k "ChartVariables"
                    // konkretne premennych
                    var es = from b
                             in ThisDoc.Descendants("chart")
                             select new ChartVariables
                             {
                                 ID = Convert.ToInt32(b.Element("id").Value),
                                 ChartType = b.Element("charttype").Value,
                                 XData = (Convert.ToInt32(b.Element("xdata").Value) - 1).ToString(),
                                 YData = (Convert.ToInt32(b.Element("ydata").Value) - 1).ToString(),
                                 AlternativeChartFirst = (Convert.ToInt32(b.Element("alternativechartfirst").Value) - 1).ToString(),
                                 AlternativeChartSecond = (Convert.ToInt32(b.Element("alternativechartsecond").Value) - 1).ToString(),
                                 IsXDataDateTime = Convert.ToBoolean(b.Element("isxdatadatetime").Value),
                                 DateTimeSource = (Convert.ToInt32(b.Element("datetimesource").Value) - 1).ToString(),
                                 PositionRow = b.Element("positionrow").Value,
                                 PositionColumn = b.Element("posiitoncolumn").Value,
                                 ChartHeading = b.Element("tittle").Value,
                                 ShowDescription = Convert.ToBoolean(b.Element("showtittle").Value),
                                 ChartWidth = Convert.ToInt32(b.Element("width").Value),
                                 ChartHeight = Convert.ToInt32(b.Element("height").Value),
                             };

                    // vymaze sa grid, blbblo to ked sa dalo Load a v loade bol napriklad iba jeden graf
                    // a na stranke boli napriklad 3
                    gr.Children.Clear();

                    foreach (ChartVariables tr in es)
                    {

                        tr.AlternativeList = alternativeList;

                        // inicializuje graf podla typu aky sa ma vykreslit
                        switch (tr.ChartType)
                        {
                            // vykresli klasicky stlpcovy 2D graf
                            case "ColumnChart2D":
                                ColumnCharts.ColumnChart2D chart = new ColumnCharts.ColumnChart2D(sort, s1, gr, tr, rows, es);
                                break;
                            // vykresli klasicky kolacovy 2D graf
                            case "PieChart2D":
                                PieChart.PieChart2D pieChart2D = new PieChart.PieChart2D(sort, s1, gr, tr, rows, es);
                                break;
                        }
                    }
                }        

            }
        }

    }
}
