using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Windows.Data.Xml;
using Windows.Data.Xml.Dom;
using Windows.Storage;
using System.Runtime.CompilerServices;

namespace FooEditor.UWP.Models
{
    public class Snippet : INotifyPropertyChanged
    {
        string _Name;
        public string Name
        {
            get
            {
                return this._Name;
            }
            set
            {
                this._Name = value;
                OnPropertyChanged();
            }
        }
        string _Data;
        public string Data
        {
            get
            {
                return this._Data;
            }
            set
            {
                this._Data = value;
                this.OnPropertyChanged();
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        public Snippet(string name, string data)
        {
            this.Name = name;
            this.Data = data;
        }
        public void OnPropertyChanged([CallerMemberName] string caller = "")
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(caller));
        }
    }

    public class SnippetCategory : INotifyPropertyChanged
    {
        string _Name;
        public string Name
        {
            get
            {
                return this._Name;
            }
            set
            {
                this._Name = value;
                OnPropertyChanged();
            }
        }
        string _FilePath;
        public string FilePath
        {
            get
            {
                return this._FilePath;
            }
            set
            {
                this._FilePath = value;
                this.OnPropertyChanged();
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        public SnippetCategory(string name, string path)
        {
            this.Name = name;
            this.FilePath = path;
        }
        public void OnPropertyChanged([CallerMemberName] string caller = "")
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(caller));
        }

    }

    class SnipeetModel
    {
        const string SnippetFolderName = "Sinppets";


        public static async Task<ObservableCollection<SnippetCategory>> LoadCategory()
        {
            ObservableCollection<SnippetCategory> items = new ObservableCollection<SnippetCategory>();

            StorageFolder snippetFolder = await ApplicationData.Current.LocalFolder.TryGetItemAsync(SnippetFolderName) as StorageFolder;
            if (snippetFolder == null)
            {
                snippetFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync(SnippetFolderName);
                StorageFolder appInstalledFolder = Windows.ApplicationModel.Package.Current.InstalledLocation;
                StorageFolder assets = await appInstalledFolder.GetFolderAsync(SnippetFolderName);
                foreach (var file in await assets.GetFilesAsync())
                {
                    var item = snippetFolder.TryGetItemAsync(file.Name);
                    if (item != null)
                        await file.CopyAsync(snippetFolder);
                }
            }

            foreach (var file in await snippetFolder.GetFilesAsync())
                items.Add(new SnippetCategory(file.Name, file.Path));

            return items;
        }

        static bool HasCategory(IEnumerable<SnippetCategory> items,string name)
        {
            foreach (SnippetCategory category in items)
                if (category.Name == name)
                    return true;
            return false;
        }

        public static async Task<ObservableCollection<Snippet>> LoadSnippets(string path)
        {

            var file = await StorageFile.GetFileFromPathAsync(path);
            XmlDocument xml = await XmlDocument.LoadFromFileAsync(file);

            XmlNodeList nodes = xml.GetElementsByTagName("sinppet");
            ObservableCollection<Snippet> items = new ObservableCollection<Snippet>();
            foreach (var node in nodes)
            {
                string name = null, data = null;
                foreach (var child in node.ChildNodes)
                {
                    switch ((string)child.LocalName)
                    {
                        case "name":
                            name = child.InnerText;
                            break;
                        case "data":
                            data = Util.Replace(child.InnerText, new string[] { "\t", "\n", "\r", "\\n" }, new string[] { "", "", "", Environment.NewLine });
                            break;
                    }
                }
                if (name == null || data == null)
                    throw new Exception(string.Format("Not found(name:{0} data:{1} path:{2})", name, data, path));
                items.Add(new Snippet(name, data));
            }
            return items;
        }

    }

    sealed class Util
    {
        public static string Replace(string s, string[] oldValues, string[] newValues)
        {
            if (oldValues.Length != newValues.Length)
                throw new ArgumentException("oldValuesとnewValuesの数が一致しません");

            StringBuilder str = new StringBuilder(s);
            for (int i = 0; i < oldValues.Length; i++)
                str = str.Replace(oldValues[i], newValues[i]);
            return str.ToString();
        }
    }
}
