using System;
using System.Collections.Generic;
using System.Xml;

namespace Creditcall.ChipDna.Client
{
    internal class ConfigFileParser : BaseConfigParser
    {
       //Names of tags in xml config file
        private static string ConnectionParameter = "Server";
        private static string ProviderNameTag = "SslHostName";
        private static string TerminalIdTag = "TerminalId";
        private static string MerchantStreetAddressTag = "MerchantStreetAddress";
        private static string MerchantCityStateZipTag = "MerchantCityStateZip";
        private static string MerchantPhoneNumberTag = "MerchantPhoneNumber";
        private static string MerchandiseDescriptionTag = "MerchandiseDescription";
        private static string SaveReceiptTag = "SaveReceipt";
        private static string PosIdTag = "PosId";
        private static string ApiKeyTag = "ApiKey";

        private const string PARAM_TAG    = "Parameter";
        private const string COMMANDS_TAG = "Command";

        private string ConfigFileName;

        private Dictionary<string, List<ExtraParameter>> commands;

        public ConfigFileParser(string configFileName)
        {
            ConfigFileName = configFileName;
            LoadXmlFile(configFileName);
            XmlNodeList commandsXml = GetNodesByTagName(COMMANDS_TAG);
            commands = new Dictionary<string, List<ExtraParameter>>();
            if (commandsXml.Count > 0)
            {
                ParseParams(commandsXml);
            }
        }

        public string TerminalId
        {
            get { return GetElementByProperties(RootNode, TerminalIdTag); }
        }

        public string PosId
        {
            get { return GetElementByProperties(RootNode, PosIdTag); }
        }

        public string ApiKey
        {
            get { return GetElementByProperties(RootNode, ApiKeyTag); }
        }

        public string ConnectAddress
        {
            get
            {
                var address = GetElementByProperties(RootNode, ConnectionParameter);
                return address!=null ? address.Substring(0, address.IndexOf(":", StringComparison.Ordinal)) : "";
            }
        }

        public string ConnectionPort
        {
            get
            {
                var port = GetElementByProperties(RootNode, ConnectionParameter);
                return port!=null ? port.Substring(port.IndexOf(":", StringComparison.Ordinal) + 1, port.Length - port.IndexOf(":", StringComparison.Ordinal) - 1) :"";
            }
        }

        public string MerchantStreetAddress
        {
            get { return GetElementByProperties(RootNode, MerchantStreetAddressTag); }
        }

        public string MerchantCityStateZip
        {
            get { return GetElementByProperties(RootNode, MerchantCityStateZipTag); }
        }

        public string MerchantPhoneNumber
        {
            get { return GetElementByProperties(RootNode, MerchantPhoneNumberTag); }
        }

        public string MerchandiseDescription
        {
            get { return GetElementByProperties(RootNode, MerchandiseDescriptionTag); }
        }
        
        public bool? SaveReceipt
        {
            get
            {
                if (GetElementByProperties(RootNode, SaveReceiptTag) == null)
                    return null;
                return Boolean.Parse(GetElementByProperties(RootNode, SaveReceiptTag));
            }
        }

        public string SslHostName
        {
            get { return GetElementByProperties(RootNode, ProviderNameTag); }
        }

        private void ParseParams(XmlNodeList nodes)
        {
            foreach(XmlElement commandNode in nodes)
            {
                if (commandNode.HasChildNodes)
                {
                    string name = commandNode.Attributes.GetNamedItem("name").Value;
                    commands[name] = new List<ExtraParameter>(commandNode.ChildNodes.Count);
                    XmlNodeList extraParams = GetNodesByTagName(commandNode, PARAM_TAG);
                    foreach (XmlElement paramNode in extraParams)
                    {
                        try
                        {
                            commands[name].Add(new ExtraParameter(paramNode));
                        }
                        catch (InvalidOperationException e)
                        {
                            Console.Error.WriteLine("Could not parse parameter tag (" + e.Message + ")");
                        }
                    }
                }
            }
        }

        public List<ExtraParameter> GetExtraParameters(string command)
        {
            try
            {
                return commands[command];
            }
            catch (KeyNotFoundException e)
            {
                return new List<ExtraParameter>();
            }
        }
    }
}
