using Newtonsoft.Json;
using System;
using System.IO;
using System.Net;
using System.Net.NetworkInformation;

namespace NKC_SDK
{
    public class NKC
    {
        #region Protected Fields

        /// <summary>
        /// file locale per persistenza BUNK
        /// </summary>
        protected string persistFileName = "data/persistFile.json";

        #endregion Protected Fields

        #region Public Constructors

        /// <summary>
        /// Classe per effettuare comunicazioni con NKC
        /// </summary>
        /// <param name="baseIp">IP di base x ping</param>
        /// <param name="baseUrl">URL di abse x chiamate REST</param>
        /// <param name="codPost">Codice posstazione/macchina x cui si fa chiamata</param>
        public NKC(string baseIp, string baseUrl, string codPost)
        {
            _baseIp = baseIp;
            _baseUrl = baseUrl;
            _codPost = codPost;
        }

        #endregion Public Constructors

        #region Protected Properties

        /// <summary>
        /// DnsName/IP di base x chaimate
        /// </summary>
        protected string _baseIp { get; set; } = "seriate.steamware.net";

        /// <summary>
        /// URL di base per la comunicazione
        ///
        /// PROD: http://seriate.steamware.net:8083/NKC/
        /// DEV:  https://localhost:44388/
        /// </summary>
        protected string _baseUrl { get; set; } = @"http://seriate.steamware.net:8083/NKC/";

        /// <summary>
        /// COD macchina x cui si effettua chiamata
        /// </summary>
        protected string _codPost { get; set; } = "";

        protected string urlAlive
        {
            get
            {
                return $"{_baseUrl}api/Alive";
            }
        }

        protected string urlAliveClock
        {
            get
            {
                return $"{_baseUrl}api/Alive/1";
            }
        }

        protected string urlCurrBunk
        {
            get
            {
                return $"{_baseUrl}api/Bunk";
            }
        }

        protected string urlCurrSheet4Mac
        {
            get
            {
                return $"{_baseUrl}api/Sheet/{_codPost}";
            }
        }

        /// <summary>
        /// URL x salvataggio dati MachineStat
        /// </summary>
        /// <returns></returns>
        protected string urlPutMachStat
        {
            get
            {
                return $"{_baseUrl}api/MachineStat";
                //return $"{_baseUrl}api/MachineStat/{_machine}";
            }
        }

        /// <summary>
        /// URL x salvataggio dati SHEET
        /// </summary>
        /// <returns></returns>
        protected string urlPutSheetList
        {
            get
            {
                return $"{_baseUrl}api/Sheet/{_codPost}";
            }
        }

        #endregion Protected Properties

        #region Public Properties

        /// <summary>
        /// Oggetto che contiene l'oggetto SHEET WorkList corrente salvato LOCALMENTE
        /// </summary>
        public SheetWorkList persistedSheetList
        {
            get
            {
                SheetWorkList answ = new SheetWorkList();
                try
                {
                    string rawdata = File.ReadAllText(persistFileName);
                    answ = JsonConvert.DeserializeObject<SheetWorkList>(rawdata);
                }
                catch (Exception exc)
                {
                    Log.Instance.Error($"Eccezione durante recupero locale della SheetList{Environment.NewLine}{exc}");
                }
                return answ;
            }
            set
            {
                try
                {
                    // serializzo oggetto
                    string rawdata = JsonConvert.SerializeObject(value);
                    // salvo in locale
                    File.WriteAllText(persistFileName, rawdata);
                }
                catch (Exception exc)
                {
                    Log.Instance.Error($"Eccezione durante salvataggio locale della SheetList{Environment.NewLine}{exc}");
                }
            }
        }

        /// <summary>
        /// Effettua test alive all'indirizzo del server
        /// </summary>
        public bool testAlive
        {
            get
            {
                bool answ = false;
                string returnData = callUrl(urlAlive);
                returnData = JsonConvert.DeserializeObject<string>(returnData);
                answ = returnData == "OK";
                // rendo!
                return answ;
            }
        }

        /// <summary>
        /// Effettua test ping all'indirizzo del server
        /// </summary>
        public DateTime testClock
        {
            get
            {
                DateTime oggi = DateTime.Today;
                DateTime answ = oggi.AddYears(-oggi.Year + 1900).AddMonths(-oggi.Month).AddDays(-oggi.Day + 1);
                // recupero!
                string returnData = callUrl(urlAliveClock);
                try
                {
                    DateTime.TryParse(JsonConvert.DeserializeObject<string>(returnData), out answ);
                }
                catch (Exception exc)
                {
                    Log.Instance.Error($"Eccezione durante testClock, ricevuto {returnData}{Environment.NewLine}{exc}");
                }
                // rendo!
                return answ;
            }
        }

        /// <summary>
        /// Effettua test ping all'indirizzo del server
        /// </summary>
        public PingReply testPing
        {
            get
            {
                Ping myPing = new Ping();
                // timeout a 1 sec!
                PingReply answ = myPing.Send(_baseIp, 1000);
                // rendo!
                return answ;
            }
        }

        #endregion Public Properties

        #region Protected Methods

        protected string urlGetBunk(int currBunkId, string CodPost)
        {
            return $"{_baseUrl}api/Bunk/{currBunkId}?showNext=false&machine={CodPost}";
        }

        protected string urlNextBunk(int currBunkId, string CodPost)
        {
            return $"{_baseUrl}api/Bunk/{currBunkId}?showNext=true&machine={CodPost}";
        }

        protected string urlPutBunk(int currBunkId)
        {
            return $"{_baseUrl}api/Bunk/{currBunkId}";
        }

        #endregion Protected Methods

        #region Public Methods

        /// <summary>
        /// Effettua chiamata URL e restituisce risultato
        /// </summary>
        /// <param name="URL"></param>
        /// <returns></returns>
        public static string callUrl(string URL)
        {
            string answ = "";
            var client = new WebClientWT();
            //var client = new WebClient();
            client.Headers.Add("user-agent", "NKC_SDK");
            try
            {
                answ = client.DownloadString(URL);
            }
            catch (Exception exc)
            {
                Log.Instance.Error($"Eccezione durante callUrl per URL: {URL}{Environment.NewLine}{exc}");
                answ = exc.Message;
            }
            // restituisco valore!
            return answ;
        }

        /// <summary>
        /// Effettua chiamata URL e restituisce risultato
        /// </summary>
        /// <param name="URL"></param>
        /// <param name="payload"></param>
        /// <returns></returns>
        public static string callUrl(string URL, string payload)
        {
            string answ = "";
            var client = new WebClientWT();
            client.Headers.Add("user-agent", "NKC_SDK");
            try
            {
                answ = client.UploadString(URL, payload);
            }
            catch (Exception exc)
            {
                Log.Instance.Error($"Eccezione durante callUrl per URL: {URL} | payload: {payload}{Environment.NewLine}{exc}");
                answ = exc.Message;
            }
            // restituisco valore!
            return answ;
        }

        /// <summary>
        /// Effettua chiamata PUT
        /// </summary>
        /// <param name="URL"></param>
        /// <param name="payload"></param>
        /// <returns></returns>
        public static string putData(string URL, string payload)
        {
            string answ = "";
            var client = new WebClientWT();
            client.Headers.Add("user-agent", "NKC_SDK");
            // importante x evitare errore 415 di dataType non ammesso
            client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
            try
            {
                // va messo "PUT" e va configurato IIS per accettare PUT
                answ = client.UploadString(URL, "PUT", payload);
                answ = "ok";
            }
            catch (Exception exc)
            {
                Log.Instance.Error($"Eccezione durante putData per {URL}{Environment.NewLine}{exc}");
                answ = exc.Message;
            }
            // restituisco valore!
            return answ;
        }

        public static PingReply testPingDevice(string address)
        {
            Ping myPing = new Ping();
            // timeout a 1 sec!
            PingReply answ = myPing.Send(address, 2000);
            // rendo!
            return answ;
        }

        /// <summary>
        /// Recupera elenco dei fogli ATTIVI
        /// - effettua chiamata tramite REST API HTTP
        /// - il risutlato viene deserializzato nell'oggetto richiesto
        /// </summary>
        /// <returns></returns>
        public SheetWorkList getCurrentSheets()
        {
            SheetWorkList answ = null;
            string rawdata = "";
            // chiamo metodo x recupero WBunk...
            try
            {
                rawdata = callUrl(urlCurrSheet4Mac);
                answ = JsonConvert.DeserializeObject<SheetWorkList>(rawdata);
            }
            catch (Exception exc)
            {
                Log.Instance.Error($"Eccezione durante getCurrentSheets, ricevuto {rawdata}{Environment.NewLine}{exc}");
            }
            return answ;
        }

        /// <summary>
        /// Effettua salvataggio dell'elenco info stati/eventi su NKC
        /// </summary>
        /// <param name="updatedInfo"></param>
        public bool saveMachStatRecords(MachineStatData updatedInfo)
        {
            bool answ = false;
            string rawdata = "";
            try
            {
                // aggiungo macchina nel codice dei fogli...
                updatedInfo.Machine = _codPost;
                // serializzo oggetto
                rawdata = JsonConvert.SerializeObject(updatedInfo);
                // invio con metodo put!
                putData(urlPutMachStat, rawdata);
                answ = true;
            }
            catch (Exception exc)
            {
                Log.Instance.Error($"Eccezione durante saveMachStatRecords, ricevuto {rawdata}{Environment.NewLine}{exc}");
            }
            return answ;
        }

        /// <summary>
        /// Effettua salvataggio dell'elenco dei fogli (1..n) su NKC
        /// </summary>
        /// <param name="updatedSheetList"></param>
        public bool saveSheets(SheetWorkList updatedSheetList)
        {
            bool answ = false;
            string rawdata = "";
            try
            {
                // aggiungo macchina nel codice dei fogli...
                updatedSheetList.Machine = _codPost;
                // serializzo oggetto
                rawdata = JsonConvert.SerializeObject(updatedSheetList);
                // invio con metodo put!
                putData(urlPutSheetList, rawdata);
                answ = true;
            }
            catch (Exception exc)
            {
                Log.Instance.Error($"Eccezione durante saveSheets, ricevuto {rawdata}{Environment.NewLine}{exc}");
            }
            return answ;
        }

        #endregion Public Methods
    }
}