using PaintDotNet.SystemLayer;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace PaintDotNet
{
    /// 
    /// Zyh
    /// 原本是继承ImageStrip
    /// copy了一个ImageNameStrip
    /// 
    internal class DocumentStrip : ImageNameStrip, IDocumentList
    {
        private List documents = new List();
        private List documentButtons = new List();
        private Dictionary dw2button = new Dictionary();
        private Dictionary thumbs = new Dictionary();
        private DocumentWorkspace selectedDocument = null;
        private bool ensureSelectedIsVisible = true;
        private AppWorkspace appWorkspace;
        public DocumentWorkspace[] DocumentList
        {
            get
            {
                return this.documents.ToArray();
            }
        }
        public int DocumentCount
        {
            get
            {
                return this.documents.Count;
            }
        }
        public event EventHandler DocumentListChanged;
        protected virtual void OnDocumentListChanged()
        {
            if (DocumentListChanged != null)
            {
                DocumentListChanged(this, EventArgs.Empty);
            }
        }
        public DocumentWorkspace SelectedDocument
        {
            get
            {
                return this.selectedDocument;
            }
            set
            {
                if (!this.documents.Contains(value))
                {
                    throw new ArgumentException("DocumentWorkspace isn't being tracked by this instance of DocumentStrip");
                }
                if (this.selectedDocument != value)
                {
                    SelectDocumentWorkspace(value);
                    OnDocumentClicked(value, DocumentClickAction.Select);
                    Refresh();
                }
            }
        }
        public int SelectedDocumentIndex
        {
            get
            {
                return this.documents.IndexOf(this.selectedDocument);
            }
        }
        private bool OnDigitHotKeyPressed(Keys keys)
        {
            keys &= ~Keys.Alt;
            keys &= ~Keys.Control;
            if (keys < Keys.D0 || keys > Keys.D9)
            {
                return false;
            }
            int digit = (int)keys - (int)Keys.D0;
            int index;
            if (digit == 0)
            {
                index = 9;
            }
            else
            {
                index = digit - 1;
            }
            if (index < this.documents.Count)
            {
                PerformItemClick(index, ItemPart.Image, MouseButtons.Left);
                return true;
            }
            else
            {
                return false;
            }
        }
        public DocumentStrip(AppWorkspace appWorkspace)
        {
            this.appWorkspace = appWorkspace;
            PdnBaseForm.RegisterFormHotKey(Keys.Delete, OnDeleteHotKeyPressed);
            PdnBaseForm.RegisterFormHotKey(Keys.Control | Keys.Tab, OnNextTabHotKeyPressed);
            PdnBaseForm.RegisterFormHotKey(Keys.Control | Keys.PageDown, OnNextTabHotKeyPressed);
            PdnBaseForm.RegisterFormHotKey(Keys.Control | Keys.Shift | Keys.Tab, OnPreviousTabHotKeyPressed);
            PdnBaseForm.RegisterFormHotKey(Keys.Control | Keys.PageUp, OnPreviousTabHotKeyPressed);
            //thumbnailManager = new ThumbnailManager(this); // allow for a 1px black border
            InitializeComponent();
            //#18291
            //for (int i = 0; i <= 9; ++i)
            //{
            //    Keys digit = Utility.LetterOrDigitCharToKeys((char)(i + '0'));
            //    PdnBaseForm.RegisterFormHotKey(Keys.Control | digit, OnDigitHotKeyPressed);
            //    PdnBaseForm.RegisterFormHotKey(Keys.Alt | digit, OnDigitHotKeyPressed);
            //}
            this.ShowCloseButtons = true;
        }
        /// 
        /// 删除按键
        /// 
        /// 
        /// 
        private bool OnDeleteHotKeyPressed(Keys keys)
        {
            if (this.selectedDocument != null)
            {
                this.selectedDocument.MouseEvent_Del(null, null);
            }
            if (this.appWorkspace!=null)
            {
                if(this.appWorkspace.cameraPreviewDialog!=null && !this.appWorkspace.cameraPreviewDialog.IsDisposed)
                {
                    if(this.appWorkspace.cameraPreviewDialog.documentWorkspace!=null)
                        this.appWorkspace.cameraPreviewDialog.documentWorkspace.MouseEvent_Del(null, null);
                }
            }
            return true;
        }
        
        private bool OnNextTabHotKeyPressed(Keys keys)
        {
            bool processed = NextTab();
            return processed;
        }
        private bool OnPreviousTabHotKeyPressed(Keys keys)
        {
            bool processed = PreviousTab();
            return processed;
        }
        public bool NextTab()
        {
            bool changed = false;
            if (this.selectedDocument != null)
            {
                int currentIndex = this.documents.IndexOf(this.selectedDocument);
                int newIndex = (currentIndex + 1) % this.documents.Count;
                SelectedDocument = this.documents[newIndex];
                changed = true;
            }
            return changed;
        }
        public bool PreviousTab()
        {
            bool changed = false;
            if (this.selectedDocument != null)
            {
                int currentIndex = this.documents.IndexOf(this.selectedDocument);
                int newIndex = (currentIndex + (this.documents.Count - 1)) % this.documents.Count;
                SelectedDocument = this.documents[newIndex];
                changed = true;
            }
            return changed;
        }
        private void InitializeComponent()
        {
            this.Name = "DocumentStrip";
        }
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                while (this.documents.Count > 0)
                {
                    RemoveDocumentWorkspace(this.documents[this.documents.Count - 1]);
                }
                /*if (this.thumbnailManager != null)
                {
                    this.thumbnailManager.Dispose();
                    this.thumbnailManager = null;
                }*/
                foreach (DocumentWorkspace dw in this.thumbs.Keys)
                {
                    RenderArgs ra = this.thumbs[dw];
                    ra.Dispose();
                }
                this.thumbs.Clear();
                this.thumbs = null;
            }
            base.Dispose(disposing);
        }
        protected override void OnScrollArrowClicked(ArrowDirection arrowDirection)
        {
            int sign = 0;
            switch (arrowDirection)
            {
                case ArrowDirection.Left:
                    sign = -1;
                    break;
                case ArrowDirection.Right:
                    sign = +1;
                    break;
            }
            int delta = ItemSize.Width;
            ScrollOffset += sign * delta;
            base.OnScrollArrowClicked(arrowDirection);
        }
        protected override void OnItemClicked(Item item, ItemPart itemPart, MouseButtons mouseButtons)
        {
            DocumentWorkspace dw = item.Tag as DocumentWorkspace;
            if (dw != null)
            {
                switch (itemPart)
                {
                    case ItemPart.None:
                        // do nothing
                        break;
                    case ItemPart.CloseButton:
                        if (mouseButtons == MouseButtons.Left)
                        {
                            OnDocumentClicked(dw, DocumentClickAction.Close);
                        }
                        break;
                    case ItemPart.Image:
                        if (mouseButtons == MouseButtons.Left)
                        {
                            SelectedDocument = dw;
                        }
                        else if (mouseButtons == MouseButtons.Right)
                        {
                            // TODO ZYH 预留右键菜单
                        }
                        break;
                    default:
                        throw new InvalidEnumArgumentException();
                }
            }
            base.OnItemClicked(item, itemPart, mouseButtons);
        }
        public event EventHandler>> DocumentClicked;
        protected virtual void OnDocumentClicked(DocumentWorkspace dw, DocumentClickAction action)
        {
            if (DocumentClicked != null)
            {
                DocumentClicked(this, new EventArgs>(
                    Pair.Create(dw, action)));
            }
        }
        public void UnlockDocumentWorkspaceDirtyValue(DocumentWorkspace unlockMe)
        {
            Item docItem = this.dw2button[unlockMe];
            docItem.UnlockDirtyValue();
        }
        public void LockDocumentWorkspaceDirtyValue(DocumentWorkspace lockMe, bool forceDirtyValue)
        {
            Item docItem = this.dw2button[lockMe];
            docItem.LockDirtyValue(forceDirtyValue);
        }
        public void AddDocumentWorkspace(DocumentWorkspace addMe)
        {
            this.documents.Add(addMe);
            ImageNameStrip.Item docButton = new ImageNameStrip.Item();
            docButton.Image = null;
            docButton.Tag = addMe;
            AddItem(docButton);
            this.documentButtons.Add(docButton);
            addMe.CompositionUpdated += Workspace_CompositionUpdated;
            this.dw2button.Add(addMe, docButton);
            if (addMe.Document != null)
            {
                QueueThumbnailUpdate(addMe);
                docButton.Dirty = addMe.Document.Dirty;
                addMe.Document.DirtyChanged += Document_DirtyChanged;
            }
            addMe.DocumentChanging += Workspace_DocumentChanging;
            addMe.DocumentChanged += Workspace_DocumentChanged;
            OnDocumentListChanged();
        }
        private void Workspace_DocumentChanging(object sender, EventArgs e)
        {
            if (e.Data != null)
            {
                e.Data.DirtyChanged -= Document_DirtyChanged;
            }
        }
        private void Workspace_DocumentChanged(object sender, EventArgs e)
        {
            DocumentWorkspace dw = (DocumentWorkspace)sender;
            ImageNameStrip.Item docButton = this.dw2button[dw];
            if (dw.Document != null)
            {
                docButton.Dirty = dw.Document.Dirty;
                dw.Document.DirtyChanged += Document_DirtyChanged;
            }
            else
            {
                docButton.Dirty = false;
            }
        }
        private void Document_DirtyChanged(object sender, EventArgs e)
        {
            for (int i = 0; i < this.documents.Count; ++i)
            {
                if (object.ReferenceEquals(sender, this.documents[i].Document))
                {
                    ImageNameStrip.Item docButton = this.dw2button[this.documents[i]];
                    docButton.Dirty = ((Document)sender).Dirty;
                }
            }
        }
        private void Workspace_CompositionUpdated(object sender, EventArgs e)
        {
            DocumentWorkspace dw = (DocumentWorkspace)sender;
            QueueThumbnailUpdate(dw);
        }
        public void RemoveDocumentWorkspace(DocumentWorkspace removeMe)
        {
            removeMe.CompositionUpdated -= Workspace_CompositionUpdated;
            if (this.selectedDocument == removeMe)
            {
                this.selectedDocument = null;
            }
            removeMe.DocumentChanging -= Workspace_DocumentChanging;
            removeMe.DocumentChanged -= Workspace_DocumentChanged;
            if (removeMe.Document != null)
            {
                removeMe.Document.DirtyChanged -= Document_DirtyChanged;
            }
            this.documents.Remove(removeMe);
            ImageNameStrip.Item docButton = this.dw2button[removeMe];
            this.RemoveItem(docButton);
            this.dw2button.Remove(removeMe);
            this.documentButtons.Remove(docButton);
            if (this.thumbs.ContainsKey(removeMe))
            {
                RenderArgs thumbRA = this.thumbs[removeMe];
                Surface surface = thumbRA.Surface;
                thumbRA.Dispose();
                this.thumbs.Remove(removeMe);
                surface.Dispose();
            }
            OnDocumentListChanged();
        }
        protected override void OnLayout(LayoutEventArgs levent)
        {
            base.OnLayout(levent);
            if (this.ensureSelectedIsVisible &&
                (!Focused && !LeftScrollButton.Focused && !RightScrollButton.Focused))
            {
                int index = this.documents.IndexOf(this.selectedDocument);
                EnsureItemFullyVisible(index);
            }
        }
        public void SelectDocumentWorkspace(DocumentWorkspace selectMe)
        {
            UI.SuspendControlPainting(this);
            this.selectedDocument = selectMe;
            if (this.thumbs.ContainsKey(selectMe))
            {
                //RenderArgs thumb = this.thumbs[selectMe];
                //Bitmap bitmap = thumb.Bitmap;
            }
            else
            {
                QueueThumbnailUpdate(selectMe);
            }
            foreach (ImageNameStrip.Item docItem in this.documentButtons)
            {
                if ((docItem.Tag as DocumentWorkspace) == selectMe)
                {
                    EnsureItemFullyVisible(docItem);
                    docItem.Checked = true;
                }
                else
                {
                    docItem.Checked = false;
                }
            }
            UI.ResumeControlPainting(this);
            Invalidate(true);
        }
        public void RefreshAllThumbnails()
        {
            foreach (DocumentWorkspace dw in this.documents)
            {
                QueueThumbnailUpdate(dw);
            }
        }
        private void OnThumbnailUpdated(DocumentWorkspace dw)
        {
            if (this.dw2button.ContainsKey(dw))
            {
                ImageNameStrip.Item docButton = this.dw2button[dw];
                docButton.Name = dw.GetFriendlyName();
                docButton.Update();
            }
        }
        public void SetDw2buttonName(DocumentWorkspace dw, string buttonName)
        {
            if (this.dw2button.ContainsKey(dw))
            {
                ImageNameStrip.Item docButton = this.dw2button[dw];
                docButton.Name = buttonName;
                docButton.Update();
            }
        }
        public void QueueThumbnailUpdate(DocumentWorkspace dw)
        {
            OnThumbnailUpdated(dw);
        }
    }
}