using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;
using System.Xml.Linq;

namespace ynhtm.Upfile
{
    using Lib;

    public partial class Main : UserControl
    {
        public Main(IDictionary<string, string> initParams)
        {
            this.Params = initParams;
            this.List = new ObservableCollection<Lib.Item>();
            InitializeComponent();
            this.cobRename.DisplayMemberPath = "Key";
            this.cobRename.SelectedValuePath = "Value";
            this.cobRename.ItemsSource = new[] { 
                new KeyValuePair<string, int>("自动命名", 0),
                new KeyValuePair<string, int>("覆盖文件", 1),
                new KeyValuePair<string, int>("重命名", 2) 
            };
        }

        protected IDictionary<string, string> Params { get; private set; }

        protected ObservableCollection<Lib.Item> List { get; private set; }

        string path;
        public string Path
        {
            get { return this.path; }
            set
            {
                if (this.path == value) return;
                this.BindPath(value);
                this.BindNav(value);
                this.path = value;
                IsolatedStorageSettings.ApplicationSettings.Save("Path", value);
            }
        }

        void AddItem(Lib.Item item, int index = -1)
        {
            var list = this.List;
            item.Click += (object sender, CancelEventArgs e) =>
            {
                if (item.Status != ItemStatus.Done)
                    e.Cancel = true;
                else if (item.ItemType == ItemType.Dir)
                {
                    e.Cancel = true;
                    this.Path = item.Url.ToString();
                }
                else
                {
                    var script = HtmlPage.Window.GetProperty("Upfile_Click") as ScriptObject;
                    if (script == null) return;
                    e.Cancel = true;
                    var url = Regex.Replace(item.Url.ToString(), "^" + Regex.Escape(new Uri(HtmlPage.Document.DocumentUri, "/").ToString()), "/", RegexOptions.IgnoreCase);
                    if (this.Params.ContainsKey("ID"))
                        script.InvokeSelf(url, this.Params["ID"].ToString());
                    else
                        script.InvokeSelf(url);
                }
            };
            item.Delete += (object sender, EventArgs e) =>
            {
                if (item.ItemType == ItemType.Dir)
                {
                    if (!HtmlPage.Window.Confirm("确认删除目录“" + item.Name + "”吗？")) return;
                    Utils.GetHttp(new Uri(HtmlPage.Document.DocumentUri, "/API/Upfile.ashx?Action=DelDir&Path=" + item.Url.ToString().UrlEncode()));
                }
                else if (item.Status == ItemStatus.Done)
                {
                    if (!HtmlPage.Window.Confirm("确认删除文件“" + item.Name + "”吗？")) return;
                    Utils.GetHttp(new Uri(HtmlPage.Document.DocumentUri, "/API/Upfile.ashx?Action=DelFile&Url=" + item.Url.ToString().UrlEncode()));
                }
                if (item.Status == ItemStatus.Post) this.SetEnabled(true);
                item.Status = ItemStatus.Canceled;
                list.Remove(item);
            };
            item.Done += (object sender, EventArgs e) =>
            {
                this.Upfile();
            };
            item.Error += (object sender, EventArgs e) =>
            {
                this.Upfile();
            };
            if (index > -1)
                list.Insert(index, item);
            else
                list.Add(item);
        }

        void BindPathXML(string xml)
        {
            this.List.Clear();
            this.SetEnabled(true);
            var doc = XDocument.Parse(xml);
            var array = doc.Root.Elements("dir");
            if (array != null)
            {
                foreach (var i in array)
                    this.AddItem(new Lib.Item(i.Element("path").Value, long.Parse(i.Element("files").Value)));
            }
            array = doc.Root.Elements("file");
            if (array != null)
            {
                foreach (var i in array)
                    this.AddItem(new Lib.Item(new Uri(i.Element("url").Value), long.Parse(i.Element("length").Value)));
            }
        }

        void BindPath(string path)
        {
            Utils.GetHttp(new Uri(HtmlPage.Document.DocumentUri, "/API/Upfile.ashx?Action=List&Path=" + path.UrlEncode()), (string s) =>
            {
                this.Dispatcher.BeginInvoke(() => { this.BindPathXML(s); });
            });
        }

        void BindNav(string path)
        {
            this.Dispatcher.BeginInvoke(() =>
            {
                this.navPanel.Children.Clear();
                var link = new HyperlinkButton() { Content = "~" };
                link.Click += (object sender, RoutedEventArgs e) =>
                {
                    this.Path = "/";
                };
                this.navPanel.Children.Add(link);
                var m = Regex.Match(path, @"([^/]+)(/|$)");
                while (m.Success)
                {
                    var n = m.Result("$1");
                    var i = m.Index;
                    var s = "/";
                    if (i > 0) s = path.Substring(0, i);
                    s += m.Value;
                    this.navPanel.Children.Add(new TextBlock() { Text = ">" });
                    link = new HyperlinkButton() { Content = n };
                    link.Click += (object sender, RoutedEventArgs e) =>
                    {
                        this.Path = s;
                    };
                    this.navPanel.Children.Add(link);
                    m = m.NextMatch();
                }
            });
        }

        void CreateDir(string path)
        {
            Utils.GetHttp(new Uri(HtmlPage.Document.DocumentUri, "/API/Upfile.ashx?Action=CreateDir&Path=" + path.UrlEncode()), (string s) =>
            {
                this.Dispatcher.BeginInvoke(() =>
                {
                    if (!s.IsNullOrWhiteSpace())
                        this.AddItem(new Lib.Item(s, 0), 0);
                });
            });
        }

        void SetEnabled(bool enabled)
        {
            this.chkPicMask.IsEnabled = enabled;
            this.cobRename.IsEnabled = enabled;
            this.btnCreateDir.IsEnabled = enabled;
            this.btnOpen.IsEnabled = enabled;
            this.btnUpfile.IsEnabled = enabled;
        }

        void Upfile()
        {
            var item = this.List.FirstOrDefault(i => i.Status == ItemStatus.None);
            if (item == null)
                this.SetEnabled(true);
            else
            {
                this.SetEnabled(false);
                item.Upfile(this.Path, this.Params["Cookie"].UrlDecode(), (bool)this.chkPicMask.IsChecked ? 1 : 0, (int)this.cobRename.SelectedValue);
            }
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            this.fileList.ItemsSource = this.List;
            var setting = IsolatedStorageSettings.ApplicationSettings;
            this.Path = setting.GetValue("Path", "/");
            this.chkPicMask.IsChecked = setting.GetValue("PicMask", true);
            this.cobRename.SelectedIndex = Math.Max(0, Math.Min(this.cobRename.Items.Count - 1, setting.GetValue<int>("Rename")));
        }

        private void UserControl_Drop(object sender, DragEventArgs e)
        {
            var files = e.Data.GetData(DataFormats.FileDrop) as FileInfo[];
            if (files == null || files.Length == 0) return;
            var list = this.List;
            var index = 0;
            foreach (var i in list)
            {
                if (i.ItemType == ItemType.File) break;
                index++;
            }
            foreach (var i in files)
            {
                if (Regex.IsMatch(i.Name, Utils.ALLOWEDPATTERN, RegexOptions.IgnoreCase))
                    this.AddItem(new Lib.Item(i, this.Dispatcher), index);
            }
        }

        private void chkPicMask_Click(object sender, RoutedEventArgs e)
        {
            IsolatedStorageSettings.ApplicationSettings.Save("PicMask", this.chkPicMask.IsChecked);
        }

        private void cobRename_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            IsolatedStorageSettings.ApplicationSettings.Save("Rename", this.cobRename.SelectedIndex);
        }

        private void btnCreateDir_Click(object sender, RoutedEventArgs e)
        {
            var win = new Win.CreateDir();
            win.Closed += (object a, EventArgs b) =>
            {
                if ((bool)win.DialogResult)
                {
                    var s = win.txtName.Text;
                    if (s.IsNullOrWhiteSpace()) return;
                    this.CreateDir(this.Path + "/" + s);
                }
            };
            win.Show();
        }

        private void btnOpen_Click(object sender, RoutedEventArgs e)
        {
            var dlg = new OpenFileDialog() { Filter = "允许上传的文件|" + Utils.ALLOWEDEXTS + "|图片文件 (*.jpg;*.jpeg;*.png;*.bmp)|*.jpg;*.jpeg;*.png;*.bmp|所有文件 (*.*)|*.*", Multiselect = true };
            if ((bool)dlg.ShowDialog())
            {
                var list = this.List;
                var index = 0;
                foreach (var i in list)
                {
                    if (i.ItemType == ItemType.File) break;
                    index++;
                }
                foreach (var i in dlg.Files)
                    this.AddItem(new Lib.Item(i, this.Dispatcher), index);
            }
        }

        private void btnUpfile_Click(object sender, RoutedEventArgs e)
        {
            this.Upfile();
        }
    }
}