using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using PXP.Crawler.API.Model;
using PXP.Crawler.API.Utils;

namespace PXP.Crawler.API.Designers
{
    public class DesignerData
    {

        public class PinState
        {
            public int index;
            public string Name;
            public string Value;            
        }



        internal Rectangle bounds = new Rectangle(10, 10, 150, 50);
        internal int cornerRadius = 5;

        internal SortedDictionary<int, PinState> pinStates = new SortedDictionary<int, PinState>();        

        public Rectangle Bounds
        {
            get { return bounds; }
            set { bounds = value; }
        }

        public int CornerRadius
        {
            get { return cornerRadius; }
            set { cornerRadius = value; }
        }

        public virtual void PutXml(XmlNode parent)
        {
            XmlElement ddEl = Misc.CreateAppendXmlElement(parent, "designer");
            XmlElement bEl = Misc.CreateAppendXmlElement(ddEl, "bounds");
            bEl.SetAttribute("x", bounds.X.ToString());
            bEl.SetAttribute("y", bounds.Y.ToString());
            bEl.SetAttribute("w", bounds.Width.ToString());
            bEl.SetAttribute("h", bounds.Height.ToString());
            ddEl.SetAttribute("crad", cornerRadius.ToString());

            XmlElement pinStatesEl = Misc.CreateAppendXmlElement(ddEl, "pin_states");
            foreach (int pinInd in pinStates.Keys)
            {
                PinState ps = pinStates[pinInd];
                
                ps.index = pinInd;

                XmlElement pinStateEl = Misc.CreateAppendXmlElement(pinStatesEl, "pin_state");
                Misc.CreateAppendXmlElement(pinStateEl, "ind", ps.index.ToString());
                Misc.CreateAppendXmlElement(pinStateEl, "name", ps.Name.ToString());
                Misc.CreateAppendXmlElement(pinStateEl, "val", WebUtility.HtmlEncode(ps.Value.ToString()));
            }
        }

        public virtual void SetXml(XmlNode parent)
        {
            XmlElement ddEl = parent["designer"];
            XmlElement bEl = ddEl["bounds"];
            Rectangle bRect = new Rectangle(
                Conv.StringToInt(bEl.GetAttribute("x"), bounds.X),
                Conv.StringToInt(bEl.GetAttribute("y"), bounds.Y),
                Conv.StringToInt(bEl.GetAttribute("w"), bounds.Width),
                Conv.StringToInt(bEl.GetAttribute("h"), bounds.Height));
            bounds = bRect;
            cornerRadius = Conv.StringToInt(ddEl.GetAttribute("crad"), cornerRadius);

            pinStates.Clear();
            XmlElement pinStatesEl = ddEl["pin_states"];
            foreach (XmlElement pinStateEl in pinStatesEl.ChildNodes)
            {
                PinState pinState = new PinState()
                {
                    index = Conv.StringToInt(Misc.GetChildElementXml(pinStateEl, "ind"), -1),
                    Name = Misc.GetChildElementXml(pinStateEl, "name"),
                    Value = WebUtility.HtmlDecode(Misc.GetChildElementXml(pinStateEl, "val"))
                };
                pinStates.Add(pinState.index, pinState);
            }
        }

        public void SetNodePinStates(Node node)
        {
            Type nodeType = node.GetType();
            foreach (PinState ps in pinStates.Values)
            {
                PropertyInfo pi = nodeType.GetProperty(ps.Name);
                if (pi != null)
                {
                    if (pi.CanWrite)
                    {
                        object pVal = null;
                        if (pi.PropertyType == typeof (int) || pi.PropertyType == typeof (long))
                        {
                            pVal = Conv.StringToInt(ps.Value, 0);
                        }
                        else if (pi.PropertyType == typeof (float) || pi.PropertyType == typeof (double))
                        {
                            pVal = Conv.StringToDouble(ps.Value, 0);
                        }
                        else if (pi.PropertyType == typeof (string))
                        {
                            pVal = ps.Value;
                        }
                        if (pVal != null)
                        {
                            pi.SetValue(node, pVal);
                        }
                    }
                }
            }


        }

        public void GetNodePinStates(Node node)
        {
            Type nodeType = node.GetType();
            foreach (PinState ps in pinStates.Values)
            {
                PropertyInfo pi = nodeType.GetProperty(ps.Name);
                if (pi != null)
                {
                    if (pi.CanRead)
                    {
                        object val = pi.GetValue(node);
                        if (val != null)
                        {
                        ps.Value = val.ToString();                            
                        }
                    }
                }
            }


        }
    }
}
