using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using nft.ui.form;

namespace nft.ui
{
    internal class WinFormWrapper : IxForm
    {
        protected readonly Form entity;
        protected readonly Dictionary<string, IxControl> ctrCache = new Dictionary<string, IxControl>();

        public WinFormWrapper(Form f){
            entity = f;
            PrepareEventHandlers();
        }

        public WinFormWrapper(Type win_form_class) :this((Form) Activator.CreateInstance(win_form_class,true)){            
        }

        protected void PrepareEventHandlers() {
            entity.Load += new EventHandler(Entity_Load);
            entity.Disposed += new EventHandler(Entity_Closed);
            entity.VisibleChanged += new EventHandler(Entity_VisibleChanged);
            // TODO What todo for OnApply?
        }

        void Entity_VisibleChanged(object sender, EventArgs e) {
            if (VisibleChanged != null)
                VisibleChanged(this, Find(sender as Control)); 
        }

        void Entity_Closed(object sender, EventArgs e) {
            if (OnClose != null)
                OnClose(this, Find(sender as Control)); 
        }

        void Entity_Load(object sender, EventArgs e) {
            if (OnOpen != null)
                OnOpen(this, Find(sender as Control)); 
        }

        public string Name {
            get {
                return entity.Name;
            }
        }

        public IxControl Find(string name) {
            IxControl c;
            if (!ctrCache.TryGetValue(name, out c)) {
                Control c0 = entity.Controls[name];
                if (c0 != null) {
                    c = CreateWrapperFor(c0);
                    ctrCache.Add(name, c);
                }
            }
            return c;
        }

        protected IxControl Find(Control c) {
            return Find(c.Name);
        }

        protected WinControlWrapper CreateWrapperFor(Control c) {
            WinControlWrapper w = new WinControlWrapper(c);
            // TODO for ControlValuesChanged
            return w;
        }

        public IEnumerator<IxControl> EnumControls() {
            return new ControlEnumerator(this).GetEnumerator();
        }

        protected sealed class ControlEnumerator : IEnumerable<IxControl>
        {
            readonly WinFormWrapper wrapper;
            public ControlEnumerator(WinFormWrapper wfw) {
                wrapper = wfw;
            }

            public IEnumerator<IxControl> GetEnumerator() {
                IxControl ret;
                foreach (Control c in wrapper.entity.Controls) {
                    ret = wrapper.Find(c);
                    yield return ret;
                }
            }

            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
                return this.GetEnumerator();
            }
        }

        public bool Visible {
            get {
                return entity.Visible;
            }
            set {
                entity.Visible = value;
            }
        }

        public event XFormEvent OnOpen;

        public event XFormEvent OnClose;

        public event XFormEvent VisibleChanged;

        public event XFormEvent ControlValuesChanged;

        public event XFormEvent OnApply;
    }
}
