using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Runtime.Serialization;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace SE290A_BackOfficeSim_CoreApi
{
    public enum ESL_ACTION
    {
        RESET,
        DEFAULT_IMAGE,
        REFRESH_IMAGE,
        RESEND_IMAGE,
        STORE_IMAGE,
        REQUEST_SETTINGS,
        LINK,
        UNLINK,
        REASSOCIATE,
        KICK_FROM_EBS,
        MOVE_TO_EBS,
        SET_LANID,
        CLEAR_LANID,
        DEACTIVATE,
        FACTORY_DEFAULT,
        RF_TEST,
        PROGRAM_MAC,
        SOUND,
        LED,
        INPUT_RESPONSE,
        // ESL Settings
        POLL_INTERVAL,
        POLL_TIMEOUT,
        SCAN_INTERVAL,
        DISPLAY_OPTIONS,
        SCAN_CHANNELS,
        TEMPERATURE,

        // EBS Actions
        REACTIVATE_START,
        REACTIVATE_STOP,
        DEACTIVATE_RANGE,
        DISCOVER,
        ADD,
        REMOVE,
        ENERGY_SCAN,
        FIRMWARE_UPDATE,
        BALANCE_ESLS,
        REFRESH_ESLS,

        // EBS Settings
        CHANNEL,
        PANID,
        LANID,
        LOCAL_NAME,

        // Others
        NONE,
        ERROR,
    };

    [XmlRootAttribute("EslServerApiObject", IsNullable = false)]
    public class EslServerApiObject
    {
        private volatile ArgumentException ParsingError = null;
        private XmlSerializer XmlEslSerializer = new XmlSerializer(typeof(EslServerApiObject));

        internal ESL_ACTION _Action = ESL_ACTION.NONE;
                
        [DefaultValue(null)]
        public string Action = null;

        [DefaultValue(null)]
        public string MAC = null;
        public string Param1 = null;
        [DefaultValue(null)]
        public string Param2 = null;
        [DefaultValue(null)]
        public string Param3 = null;
        [DefaultValue(null)]
        public string Param4 = null;
        [DefaultValue(null)]
        public string Param5 = null;

        public string Result = "Unknown";

        [DefaultValue(null)]
        public string XApiKey = null;

        public EslServerApiObject()
        {
            XmlEslSerializer.UnknownNode += new XmlNodeEventHandler(OnEslServerApiObject_UnknownNode);
            XmlEslSerializer.UnknownAttribute += new XmlAttributeEventHandler(OnEslServerApiObject_UnknownAttribute);
        }

        public EslServerApiObject(String Action, string MAC, string result, string XApiKey = null, object Param1=null, object Param2 = null, object Param3 = null, object Param4 = null, object Param5 = null)
        {
            this.Action = String.IsNullOrEmpty(Action) ? null : Action;
            this.MAC = MAC;
            this.Result = result;
            this.XApiKey = XApiKey;
            this.Param1 = (Param1 != null && !Convert.IsDBNull(Param1)) ? Param1.ToString() : null;
            this.Param2 = (Param2 != null && !Convert.IsDBNull(Param2)) ? Param2.ToString() : null;
            this.Param3 = (Param3 != null && !Convert.IsDBNull(Param3)) ? Param3.ToString() : null;
            this.Param4 = (Param4 != null && !Convert.IsDBNull(Param4)) ? Param4.ToString() : null;
            this.Param5 = (Param5 != null && !Convert.IsDBNull(Param5)) ? Param5.ToString() : null;
        }
        
        public EslServerApiObject(string filename)
        {
            XmlEslSerializer.UnknownNode += new XmlNodeEventHandler(OnEslServerApiObject_UnknownNode);
            XmlEslSerializer.UnknownAttribute += new XmlAttributeEventHandler(OnEslServerApiObject_UnknownAttribute);

            StreamReader reader = new StreamReader(filename);

            DeserializeFromXml(reader);
        }

        public EslServerApiObject(StreamReader reader)
        {
            XmlEslSerializer.UnknownNode += new XmlNodeEventHandler(OnEslServerApiObject_UnknownNode);
            XmlEslSerializer.UnknownAttribute += new XmlAttributeEventHandler(OnEslServerApiObject_UnknownAttribute);

            DeserializeFromXml(reader);
        }
        protected void OnEslServerApiObject_UnknownNode(object sender, XmlNodeEventArgs e)
        {
            string message = "Unknown Node: '" + e.Name + "' in XML document (" + e.LineNumber + ", " + e.LinePosition + ").";

            ParsingError = new ArgumentException(message);
        }

        protected void OnEslServerApiObject_UnknownAttribute(object sender, XmlAttributeEventArgs e)
        {
            System.Xml.XmlAttribute attr = e.Attr;
            string message = "Unknown Attribute " + attr.Name + "='" + attr.Value + "' in XML document (" + e.LineNumber + ", " + e.LinePosition + ").";

            ParsingError = new ArgumentException(message);
        }

        public void SerializeToXML(string filename)
        {
            TextWriter textWriter = new StreamWriter(filename);

            XmlEslSerializer.Serialize(textWriter, this);
            textWriter.Close();
        }

        public void DeserializeFromXml(StreamReader reader)
        {
            try
            {
                XmlTextReader tr = new XmlTextReader(reader);
                tr.Namespaces = false;

                EslServerApiObject parsedObject = (EslServerApiObject)XmlEslSerializer.Deserialize(tr);

                try
                {
                    this._Action = (ESL_ACTION)Enum.Parse(typeof(ESL_ACTION), parsedObject.Action, true);
                }
                catch { }

                this.Action = parsedObject.Action;
                this.MAC = parsedObject.MAC;
                this.XApiKey = parsedObject.XApiKey;
                this.Result = parsedObject.Result;
                this.Param1 = parsedObject.Param1;
                this.Param2 = parsedObject.Param2;
                this.Param3 = parsedObject.Param3;
                this.Param4 = parsedObject.Param4;
                this.Param5 = parsedObject.Param5;
            }
            catch (InvalidOperationException e)
            {
                ParsingError = new ArgumentException(e.Message);
            }
        }
    }
}

