using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using System.ServiceModel;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using Newtonsoft.Json.Linq;
using System.Configuration;
using System.Net;
using System.Windows;
using cosicomodo.quantycaReference;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.Schema;
using System.Security.Cryptography;

namespace cosifacile
{
    public class ServiceLayer
    {
        private Utils ut = new Utils();
        string rtpID = ConfigurationManager.AppSettings["retailPointID"].ToString();

        public int initRP()
        {
            int retValue = 0;

            return retValue;
        }

        public RetailPoint getRetailPoint(string rpID)
        {
            RetailPoint retVal = new RetailPoint();

            if (retVal.rpId == 0)
            {

                try
                {
                    ut.logMsg("Cerco RetailPoint " + rpID);
                    TimedWebClient webClient = new TimedWebClient();
                    webClient.Timeout = 5000;
                    string checkAddress = string.Format(ConfigurationManager.AppSettings["urlCheckRetailPoint"], rpID);
                    string json = webClient.DownloadString(checkAddress);
                    //json = Regex.Replace(webClient.DownloadString(checkAddress), "\n", "");

                    JObject o = JObject.Parse(json);
                    if (!Boolean.Equals(o["ret"], null))
                    {
                        JToken oRp = o["ret"]["retailpoint"];
                        JToken oImg = o["ret"]["img"];
                        JToken oSettings = o["ret"]["settings"];
                        retVal = new RetailPoint(Convert.ToInt32(oRp["sign_id"]), oRp["name"].ToString(), oImg["dir"].ToString());
                        JToken oRpPromo = o["ret"]["promos"];
                        retVal.closingCards = o["ret"]["retailpoint"]["closingcards"].ToString();
                        retVal.address = o["ret"]["retailpoint"]["address"].ToString();
                        retVal.rpText = o["ret"]["retailpoint"]["courtesypagetext"].ToString();//courtesypagetext
                        foreach (JToken current in oRpPromo)
                        {
                            string imgPath = string.Format(ConfigurationManager.AppSettings["urlPromoImg"], retVal.imgPath, current["id"].ToString());
                            retVal.rpPromos.Add(new Promotion(Convert.ToInt32(current["id"]), current["name"].ToString(), imgPath));
                        }

                        retVal.adCd1 = o["ret"]["retailpoint"]["adCd1"].ToString();
                        retVal.adCd2 = o["ret"]["retailpoint"]["adCd2"].ToString();
                        retVal.cli = o["ret"]["retailpoint"]["cli"].ToString();
                        retVal.adAudiofile = o["ret"]["retailpoint"]["adAudiofile"].ToString();

                        retVal.settings = getSettings(o["ret"]["settings"]);
                        retVal.modeType = Convert.ToInt32(o["ret"]["retailpoint"]["modetype_id"].ToString());
                    }
                }
                catch (Exception ex)
                {
                    ut.logMsg("Problema di rete");
                    ut.logError(ex);
                    MessageBox.Show("Problema di rete, impossibile inizializzare il totem");
                    System.Environment.Exit(-1);
                    return null;
                }
            }
            return retVal;
        }

        public void insertAppLog(string rpID, int op, string datas)
        {
            try
            {
                TimedWebClient webClient = new TimedWebClient();
                webClient.Timeout = 5000;
                string urlAppLog = string.Format(ConfigurationManager.AppSettings["urlAppLog"] + "?id=" + rpID + "&op=" + op + "&datas=" + datas);
                string json = webClient.DownloadString(urlAppLog);
            }
            catch { }
        }

        public serviceSettings getSettings(JToken settingsToken)
        {
            serviceSettings retvalue = new serviceSettings();
            retvalue.urlGetOrder = settingsToken["urlGetOrder"].ToString();
            retvalue.urlPickOrder = settingsToken["urlPickOrder"].ToString();
            retvalue.serviceUserName = settingsToken["serviceUserName"].ToString();
            retvalue.servicePassword = settingsToken["servicePassword"].ToString();
            //retvalue.insegna = settingsToken["insegna"].ToString();
            //retvalue.socio = settingsToken["socio"].ToString();
            retvalue.insegna = ConfigurationManager.AppSettings["insegna"].ToString();
            retvalue.socio = ConfigurationManager.AppSettings["socio"].ToString();
            retvalue.sistema = settingsToken["sistema"].ToString();
            retvalue.readCodeTimeout = Convert.ToInt32(settingsToken["readCodeTimeout"].ToString());
            retvalue.orderTimeout = Convert.ToInt32(settingsToken["orderTimeout"].ToString());
            retvalue.pickTimeout = Convert.ToInt32(settingsToken["pickTimeout"].ToString());
            retvalue.carouselTimeout = Convert.ToInt32(settingsToken["carouselTimeout"].ToString());
            retvalue.productTimeout = Convert.ToInt32(settingsToken["productTimeout"].ToString());
            retvalue.adUsr = settingsToken["adUser"].ToString();
            retvalue.adPwd = settingsToken["adPwd"].ToString();
            retvalue.adCli = settingsToken["adCli"].ToString();

            return retvalue;
        }

        public class TimedWebClient : WebClient
        {
            public int Timeout { get; set; }

            public TimedWebClient()
            {
                this.Timeout = Convert.ToInt32(ConfigurationManager.AppSettings["webClientTimer"]);
            }

            protected override WebRequest GetWebRequest(Uri address)
            {
                var objWebRequest = base.GetWebRequest(address);
                return objWebRequest;
            }
        }

        private static bool CertificateHandler(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors SSLerror)
        {
            return true;
        }

        public statusType getOrders(string idOrder, string idCartafedelta, readType check, out getOrdersOutputType oType, RetailPoint rp)
        {
            ut.logMsg("Servizio getOrders");
            ut.logMsg("idOrder: " + idOrder);
            ut.logMsg("idCartafedelta: " + idCartafedelta);
            statusType retValue = new statusType();
            getOrdersInputType goit = new getOrdersInputType();
            oType = new getOrdersOutputType();
            getOrdersBinding gob = new getOrdersBinding();
            try
            {

                gob.Url = rp.settings.urlGetOrder;
                if(ConfigurationManager.AppSettings["mockService"] == "On")
                {
                    gob.Url = ConfigurationManager.AppSettings["mockServiceUrl"].ToString();
                }

                gob.UseDefaultCredentials = true;
                gob.Timeout = Convert.ToInt32(ConfigurationManager.AppSettings["webClientTimer"]);
                propertiesType ordProperties = new propertiesType();
                ordProperties.insegna = rp.settings.insegna; ;
                ordProperties.socio = rp.settings.socio;
                ordProperties.insegna = ConfigurationManager.AppSettings["serviceInsegna"];
                ordProperties.socio = ConfigurationManager.AppSettings["serviceSocio"];
                ordProperties.sistRichiedente = rp.settings.sistema;

                getOrdersInputType ordContent = new getOrdersInputType();
                string logdata = "";
                if (check == readType.Order) //(!string.IsNullOrEmpty(idOrder))
                {
                    ordContent.idOrdine = idOrder;
                    logdata = "idOrdine: " + idOrder;
                }
                else
                {
                    if (idCartafedelta.Length < 13)
                    {
                        for (int i = idCartafedelta.Length; i < 13; i++)
                        {
                            idCartafedelta = "0" + idCartafedelta;
                        }
                    }
                    ordContent.idCartaFedelta = idCartafedelta;
                    ordContent.dataRicerca = DateTime.Now.AddDays(-10).ToString("yyyyMMddHHmmss");
                    logdata = "idCartaFedelta: " + idCartafedelta;
                }

                /////faccio log dell'operazione
                insertAppLog(rp.rpId.ToString(), 1, logdata);

                gob.Credentials = new System.Net.NetworkCredential(rp.settings.serviceUserName, rp.settings.servicePassword, "");
                System.Net.ServicePointManager.ServerCertificateValidationCallback = CertificateHandler;
                ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
                retValue = gob.getOrdersOperation(ordProperties, ordContent, out oType);
                ut.logMsg("Servizio getOrders completato");



            }
            catch (Exception ex)
            {
                ut.logError(ex);
            }
            return retValue;

        }

        public statusType orderToDelivery(string[] idOrders, out orderToDeliveryOutputType otdot, RetailPoint rp, bool assistenza)
        {
            ut.logMsg("Servizio orderToDelivery");
            string logdata = "";
            foreach(string current in idOrders)
            {
                ut.logMsg("idOrdine: " + current);
                logdata += "idOrdine: " + current + ";";
            }
            statusType retValue = new statusType();
            orderToDeliveryBinding odb = new orderToDeliveryBinding();
            orderToDeliveryInputType ordContent = new orderToDeliveryInputType();
            otdot = new orderToDeliveryOutputType();
            serviceSettings sSettings = rp.settings;
            try
            {
                odb.Url = sSettings.urlPickOrder;
                odb.UseDefaultCredentials = true;
                odb.Timeout = Convert.ToInt32(ConfigurationManager.AppSettings["webClientTimer"]);
                odb.Credentials = new System.Net.NetworkCredential(sSettings.serviceUserName, sSettings.servicePassword, "");
                System.Net.ServicePointManager.ServerCertificateValidationCallback = CertificateHandler;
                ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

                propertiesType ordProperties = new propertiesType();
                ordProperties.insegna = sSettings.insegna; ;
                ordProperties.socio = sSettings.socio;

                ordProperties.insegna = ConfigurationManager.AppSettings["serviceInsegna"];
                ordProperties.socio = ConfigurationManager.AppSettings["serviceSocio"];

                ordProperties.sistRichiedente = sSettings.sistema;

                ordContent.flagRichiestaAssistenza = assistenza;
                ordContent.flagRichiestaAssistenzaSpecified = assistenza;
                ordContent.idPuntoVendita = this.rtpID.ToString();
                ordContent.ordini = new string[idOrders.Length];

                for (int i = 0; i < idOrders.Length; i++)
                {
                    ordContent.ordini[i] = idOrders[i];
                }
                if (ConfigurationManager.AppSettings["skipDelivery"] == "On")
                {
                    throw new Exception("Modalità debug, Order to delivery non eseguita");
                }
                /////faccio log dell'operazione
                insertAppLog(rp.rpId.ToString(), 2, logdata);

                retValue = odb.orderToDeliveryOperation(ordProperties, ordContent, out otdot);
                ut.logMsg("Servizio orderToDelivery Completato");
            }
            catch (Exception ex)
            {
                ut.logError(ex);
            }
            return retValue;
        }

        public String autodialer(System.Collections.Specialized.NameValueCollection reqparam)
        {
            using (TimedWebClient client = new TimedWebClient())
            {
                //reqparam = null;
                //reqparam = new System.Collections.Specialized.NameValueCollection();
                //reqparam.Add("data", "39031778912");
                string encodingJson = "";
                try
                {
                    byte[] responsebytes = client.UploadValues(@"http://selexgc.plink.it/call.php", "POST", reqparam);
                    encodingJson = Encoding.UTF8.GetString(responsebytes);

                }
                catch (Exception e)
                {
                    ut.logError(e);
                }
                return encodingJson;
            }
        }

        private static void ValidationCallBack(object sender, ValidationEventArgs e)
        {
            //Console.WriteLine("Validation Error: {0}", e.Message);
        }
    }
}
