using System;
using System.Collections;
using System.Collections.Generic;
using nft.util;
using nft.framework;
using System.Drawing;
using System.Diagnostics;
using nft.framework.drawing;
using System.Xml;
using nft.framework.plugin;

namespace nft.ui.command {
    public abstract class CommandUI {
        public static readonly int IconIndexUnassinged = -1;
        protected CommandUI() { }

        public CommandUI(Contribution owner, XmlElement e) {
            string cap = XmlUtil.GetSingleNodeText(e, "caption", null);
            this.capShort = XmlUtil.GetSingleNodeText(e, "short-caption", cap);
            this.capLong = XmlUtil.GetSingleNodeText(e, "long-caption", cap);
            this.desc = XmlUtil.GetSingleNodeText(e, "description", null);
            XmlElement eico = e.SelectSingleNode("icon") as XmlElement;
            if (eico != null) {
                string iconpath = XmlUtil.GetSingleNodeText(e, "icon", null);
                this.icon = PluginImageManager.GetBundledImageRef(owner, iconpath);
                XmlAttribute xa = eico.Attributes["index"];
                if (xa != null) {
                    this.iconIdx = int.Parse(xa.Value);
                }
            }            
            XmlElement ent = e.SelectSingleNode("entity") as XmlElement;
            if (ent != null) {
                this.entity = LoadEntityFromManifest(ent);
            }
        }

        public CommandUI(string caption, string description, ImageRef iconref) {
            this.capShort = caption;
            this.capLong = caption;
            this.desc = description;
            this.icon = iconref;
        }

        public CommandUI(string caption, ImageRef iconref) {
            this.capShort = caption;
            this.capLong = caption;
            this.desc = null;
            this.icon = iconref;
        }

        public event EventHandler CaptionChanged;

        protected string capShort;
        public string ShortCaption {
            get { return capShort; }
            set {
                if (capShort != value) {
                    capShort = value;
                    if (CaptionChanged != null) {
                        CaptionChanged(this, null);
                    }
                }
            }
        }

        protected string capLong;
        public string LongCaption {
            get { return capLong; }
            set {
                if (capLong != value) {
                    capLong = value;
                    if (CaptionChanged != null) {
                        CaptionChanged(this, null);
                    }
                }
            }
        }

        public event EventHandler DescriptionChanged;

        protected string desc;
        public string Description {
            get { return desc; }
            set {
                if (desc != value) {
                    desc = value;
                    if (DescriptionChanged != null) {
                        DescriptionChanged(this, null);
                    }
                }
            }
        }

        public event EventHandler IconChanged;

        protected ImageRef icon;
        public ImageRef Icon {
            get { return icon; }
            set {
                if (icon != value) {
                    icon = value;
                    if (IconChanged != null) {
                        IconChanged(this, null);
                    }
                }
            }
        }

        protected int iconIdx = IconIndexUnassinged;
        public int IconIndex {
            get { return iconIdx; }
            set {
                if (iconIdx != value) {
                    iconIdx = value;
                    if (IconChanged != null) {
                        IconChanged(this, null);
                    }
                }
            }
        }

        protected ICommandEntity entity;
        public virtual ICommandEntity CommandEntity {
            get { return entity; }
            set {
                if (entity != null) {
                    if (entity.Equals(value)) {
                        return;
                    } else {
                        entity.EnableChanged -= new EventHandler(OnEntityEnableChanged);
                    }
                } else if(value==null){
                    return;
                }
                bool b = Enable;
                entity = value;
                if (entity != null) {
                    entity.EnableChanged += new EventHandler(OnEntityEnableChanged);
                }
                if (b != Enable) {
                    FireEnableChangedEvent(this, null);
                }
            }
        }
        
        protected void OnEntityEnableChanged(object sender, EventArgs e) {
            if (UI_Enabled) {
                FireEnableChangedEvent(this, e);
            }
        }

        public bool EntityEnabled {
            get {
                return (entity != null && entity.Enable);
            }
        }

        public bool Enable {
            get {
                return enable && EntityEnabled;
            }
        }

        public event EventHandler EnableChanged;

        protected bool enable;
        public bool UI_Enabled {
            get {
                return enable;
            }
            set {
                bool b = Enable;
                enable = value;
                if (b != Enable) {
                    FireEnableChangedEvent(this, null);
                }
            }
        }

        protected void FireEnableChangedEvent(object sender, EventArgs arg) {
            if (EnableChanged != null) {
                EnableChanged(sender, arg);
            }
        }

        protected virtual ICommandEntity LoadEntityFromManifest(XmlElement e) {
            object[] args = new object[] { e };
            object ret = PluginUtil.loadObjectFromManifest(e, args);
            return (ICommandEntity)ret;
        }
    }

    public class TriggerCommandUI : CommandUI {
        protected TriggerCommandUI() { }

        public TriggerCommandUI(Contribution owner, XmlElement e)
            : base(owner, e) {
        }

        public TriggerCommandUI(string caption, string description, ImageRef iconref) :
            base(caption, description, iconref) {
        }
    }

    public delegate void SelectionEventHandler(SingleSelFixedListUI sender, SelectionEventArgs args);

    public class SingleSelFixedListUI : CommandUI {
        protected SingleSelFixedListUI() { }

        public SingleSelFixedListUI(Contribution owner, XmlElement e)
            : base(owner, e) {
        }
       
        public SingleSelFixedListUI(string caption, string description, ImageRef iconref, IDictionary<string, TriggerCommandUI> subitems) :
            base(caption, description, iconref) {
            subcmds = new Dictionary<string, TriggerCommandUI>(subitems);
        }

        public ISingleSelectCommandEntity CommandEntity {
            get { return base.CommandEntity as ISingleSelectCommandEntity; }
            set {
                ISingleSelectCommandEntity old = CommandEntity;
                if (old != value) {
                    if (old != null) {
                        old.SelectionChanged -= new ListModelventHandler(OnEntitySelectionChanged);
                    }
                    base.CommandEntity = value;
                    if (value != null) {
                        value.SelectionChanged += new ListModelventHandler(OnEntitySelectionChanged);
                        OnEntityEnableChanged(value, null);
                    }
                }
            }
        }

        protected virtual void OnEntitySelectionChanged(ISingleSelectCommandEntity sender, EventArgs e) {
            string cur = sender.Current;
            if ((cur == null && selectedName == null) || cur.Equals(selectedName)) {
                return;
            }
            string prv = selectedName;
            selectedName = cur;
            FireSelctionChangedEvent(cur, prv);
        }

        protected Dictionary<string, TriggerCommandUI> subcmds;
        public ICollection<TriggerCommandUI> SubCommands {
            get { return subcmds.Values; }
        }

        protected string selectedName;
        public string SelectionName {
            get {
                return selectedName;
            }
        }
        public TriggerCommandUI Selection {
            get {
                if (entity != null) {
                    string s = CommandEntity.Current;
                    Debug.Assert((s == null && selectedName == null) || s.Equals(selectedName));
                    return subcmds[s];
                } else {
                    return null;
                }
            }
        }

        public event SelectionEventHandler SelectionChanged;
        protected void FireSelctionChangedEvent(string cur, string prv) {
            if (SelectionChanged != null) {
                SelectionChanged(this, new SelectionEventArgs(cur, prv));
            }
        }

        internal protected virtual void OnSubCommandEnableChanged(object sender, EventArgs e) {
            FireEnableChangedEvent(sender, null);
        }

    }

    public class SelectionEventArgs : EventArgs {
        public readonly string Previous;
        public readonly string Current;
        public SelectionEventArgs(string cur, string prv) {
            this.Previous = prv;
            this.Current = cur;
        }
    }
}
