using System;
using System.Linq;
using System.Collections.ObjectModel;
using System.Runtime.Serialization;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Input;
using Windows.ApplicationModel.Store;
using Windows.Storage;
using Windows.Storage.AccessCache;
using Windows.Storage.Pickers;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace FooEditor
{
    class DocumentCollectionEventArgs
    {
        public int ActiveIndex;
        public DocumentCollectionEventArgs(int index)
        {
            this.ActiveIndex = index;
        }
    }

    [CollectionDataContract]
    class DocumentCollection : ObservableCollection<DocumentPageInfo>
    {
        public static DocumentPageInfo Empty = new DocumentPageInfo();

        [DataMember]
        int _CurrentDocumentIndex;

        public DocumentCollection()
        {
            this.Initialize();
        }

        private void Initialize()
        {
            this.ActiveDocumentChanged += (s, e) => { };
            this.CollectionChanged += (s, e) => { };
            this.PropertyChanged += (s, e) => { };
        }

        public DocumentPageInfo Current
        {
            get
            {
                if (this.Count == 0)
                    return DocumentCollection.Empty;
                else
                    return this[_CurrentDocumentIndex];
            }
        }

        public bool hasDirtyDoc
        {
            get;
            private set;
        }

        public void SaveDocumentCollection(System.IO.Stream fs)
        {
            DataContractSerializer serializer = new DataContractSerializer(typeof(DocumentCollection));
            serializer.WriteObject(fs, this);
            this.hasDirtyDoc = false;
            System.Diagnostics.Debug.WriteLine("AutoSaved");
        }

        void Document_Update(object sender, EventArgs e)
        {
            this.hasDirtyDoc = true;
        }

        public event EventHandler<DocumentCollectionEventArgs> ActiveDocumentChanged;

        public async Task AddFromFile(StorageFile file)
        {
            if (file != null)
            {
                if (this.ActiveDocument(file.Name))
                    return;

                DocumentControl doc = new DocumentControl();
                doc.Title = file.Name;

                DocumentPageInfo info = new DocumentPageInfo(doc);
                this.AddDocument(info);
                this.ActiveDocument(info);

                await doc.LoadFile(new FileModel(file));
                StorageApplicationPermissions.MostRecentlyUsedList.Add(file, "mrufile");
            }
        }

        public async Task AddFromFilePicker()
        {
            FileOpenPicker openPicker = new FileOpenPicker();

            openPicker.ViewMode = PickerViewMode.List;

            openPicker.FileTypeFilter.Add("*");

            openPicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
            StorageFile file = await openPicker.PickSingleFileAsync();
            if (file != null)
            {
                await this.AddFromFile(file);
            }
        }

        public static async Task CleanUp()
        {
            var files = await ApplicationData.Current.LocalFolder.GetFilesAsync();
            foreach (var file in files)
            {
                if (file.Name.IndexOf(DocumentModel.prefixFileName) != -1)
                    await file.DeleteAsync();
            }
        }

        public void RemoveDocument(DocumentPageInfo param)
        {
            param.doc.Updated -= Document_Update;
            param.doc.Dispose();

            int index = this.IndexOf(param);
            if (index != -1)
            {
                this.RemoveAt(index);
                if(this.Count > 0)
                    this.ActiveDocument(index == 0 ? 0 : index - 1);
            }
        }

        public void AddDocument(DocumentPageInfo info)
        {
            info.doc.Updated += Document_Update;
            this.Add(info);
            this.ActiveDocument(info);
            this.hasDirtyDoc = true;
        }

        public void Next()
        {
            int selIndex = this._CurrentDocumentIndex + 1;
            if (selIndex > this.Count - 1)
                selIndex = 0;
            this.ActiveDocument(selIndex);
        }

        public void Prev()
        {
            int selIndex = this._CurrentDocumentIndex - 1;
            if (selIndex < 0)
                selIndex = this.Count - 1;
            this.ActiveDocument(selIndex);
        }

        public void ActiveDocument(int index)
        {
            DocumentPageInfo info = this[index];
            info.ApplyCurrentSetting();
            _CurrentDocumentIndex = index;
            this.ActiveDocumentChanged(this, new DocumentCollectionEventArgs(index));
        }

        public void ActiveDocument(DocumentPageInfo info)
        {
            this.ActiveDocument(this.IndexOf(info));
        }

        public bool ActiveDocument(string file_name)
        {
            foreach (DocumentPageInfo doc_info in this)
            {
                if (doc_info.Title == file_name)
                {
                    this.ActiveDocument(doc_info);
                    return true;
                }
            }
            return false;
        }

        [OnDeserializing]
        private void SetValuesOnDeserializing(StreamingContext context)
        {
            Initialize();
        }
    }
}
