using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using System.IO.Ports;
using System.Web.Services;
using System.Configuration;
using System.Web.Http.Cors;

[EnableCors(origins: "*", headers: "*", methods: "*")]
public partial class _Default : System.Web.UI.Page
{
    private Custom.CeFCom.CeFCom comunicationElement;

    
    protected void Page_Load(object sender, EventArgs e)
    {
        try { 
            string json = Request.Params["json"].ToString();
            string id = Request.Params["id"].ToString();

            if (!string.IsNullOrEmpty(json))
            {
                string result = codifica(id, json);
                //string result = "OK";
                if (result != "OK")
                {
                    throw new System.ArgumentException(result, "original");
                }
                display.Text = "Ricevuta n." + id.Split('|')[0] + " stampata";
            
            //throw new System.ArgumentException("Errore avvenuto durante la stampa", "original");
            }
        }catch(Exception ex) {
            throw new System.ArgumentException(ex.Message, "errore");
        }


        //return result;
        /*
        string id_ricevuta = Request.QueryString["ID"];
        if (!string.IsNullOrEmpty(id_ricevuta))
        {
            string _json = JsonMaker(id_ricevuta);
            string _codifica = codifica(id_ricevuta, _json);
        }
        */

    }

    public string codifica(string _id, string inputString)
    {

        string debug = ConfigurationManager.AppSettings.Get("Debug");

        comunicationElement = new Custom.CeFCom.CeFCom();
        string codice = "";
        JObject myJson;
        JObject data;
        try { myJson = JObject.Parse(inputString); }
        catch (Exception e) { return "ERROR:" + e.Message; }

        int tipoOperazione = int.Parse(myJson.GetValue("tipo_operazione").ToString());
        switch (tipoOperazione)
        {
            case 1:
                int count1 = myJson.GetValue("data").Count();
                codice += "63001" + count1 + "\n";

                char PITCH = '1';
                /* PITCH intestazione
                1 = normale
                2 = grassetto
                3 = font 42 caratteri
                4 = doppia altezza
                5 = doppia larghezza
                6 = corsivo
                l = numero icona
                */

                for (int i = 0; i < count1; i++)
                {
                    JObject riga1 = JObject.Parse(myJson.GetValue("data")[i].ToString());
                    string descrizione1 = riga1.GetValue("descrizione").ToString();
                    string num_riga1 = riga1.GetValue("num_riga").ToString();
                    codice += "63002" + num_riga1 + PITCH + descrizione1.Length.ToString() + descrizione1 + "\n";
                }

                break;
            case 2:
                data = JObject.Parse(myJson.GetValue("data").ToString());
                int count2 = data.GetValue("righe").Count();
                for (int i = 0; i < count2; i++)
                {
                    JObject riga2 = JObject.Parse(data.GetValue("righe")[i].ToString());
                    string tipo_riga2 = riga2.GetValue("tipo_riga").ToString();
                    string descrizione2 = riga2.GetValue("descrizione").ToString();
                    string importo2 = riga2.GetValue("importo").ToString().Replace(".", "");
                    string ID_IVA = riga2.GetValue("cod_reparto").ToString();

                    
                    if (debug == "true")
                    {
                        importo2 = "00,01";
                    }

                    //Gestione formato dei decimali (50.55 = 5055)
                    if (importo2.Contains(","))
                        importo2 = importo2.Split(',')[0] + (importo2.Split(',')[1].Length == 2 ? importo2.Split(',')[1] : importo2.Split(',')[1] + "0");
                    else
                        importo2 = importo2 + "00";

                    string zeros = "";
                    for (int j = 0; j < (9 - importo2.Length); j++)
                    {
                        zeros += "0";
                    }
                    importo2 = zeros + importo2;

                    if (tipo_riga2 == "0")
                    {
                        //Riga aggiuntiva descrittiva
                        if (descrizione2.Length > 32)
                        {
                            string desc_part1 = descrizione2.Substring(0, 32);
                            string desc_part2 = descrizione2.Substring(32);

                            codice += "3002" + "1" + ((desc_part1.Length >= 10) ? desc_part1.Length.ToString() : ("0" + desc_part1.Length.ToString())) + desc_part1 + "\n";
                            codice += "3002" + "1" + ((desc_part2.Length >= 10) ? desc_part2.Length.ToString() : ("0" + desc_part2.Length.ToString())) + desc_part2 + "\n";
                        }
                        else
                        {
                            codice += "3002" + "1" + ((descrizione2.Length >= 10) ? descrizione2.Length.ToString() : ("0" + descrizione2.Length.ToString())) + descrizione2 + "\n";
                        }
                    }
                    else
                    {
                        //Riga di dettaglio ricevuta
                        //codice += "3001" + tipo_riga2 + ((descrizione2.Length >= 10) ? descrizione2.Length.ToString() : ("0" + descrizione2.Length.ToString())) + descrizione2 + importo2 + "\n";

                        string desc_len = ((descrizione2.Length >= 10) ? descrizione2.Length.ToString() : ("0" + descrizione2.Length.ToString()));
                                //command  -  tipo  -    quantità -  reparto -   len  --   descrizione  -  importo - ID IVA
                        codice += "3301" + tipo_riga2 + "000001000" + "0"+ ID_IVA + desc_len +  descrizione2  + importo2 + "00" + "\n";
                                                
                    }


                    //codice = "";
                    //codice += "3301100000000000116Articolo di test00000000001\n"; // + tipo_riga2 + ((descrizione2.Length >= 10) ? descrizione2.Length.ToString() : ("0" + descrizione2.Length.ToString())) + descrizione2 + importo2 + "\n";

                }


                //Riga descrizione pagamento e totale ricevuta

                string descrPagamento = data.GetValue("descr_pagamento").ToString();
                string descrPagamento_Length = ((descrPagamento.Length >= 10) ? descrPagamento.Length.ToString() : ("0" + descrPagamento.Length.ToString()));
                string importo_pagamento = data.GetValue("importo_pagamento").ToString().Replace(".", "");

                if (importo_pagamento.Contains(",")) //Gestione formato dei decimali (50.55 = 5055)
                    importo_pagamento = importo_pagamento.Split(',')[0] + (importo_pagamento.Split(',')[1].Length == 2 ? importo_pagamento.Split(',')[1] : importo_pagamento.Split(',')[1] + "0");
                else
                    importo_pagamento = importo_pagamento + "00";

                string _zeros = "";
                for (int j = 0; j < (9 - importo_pagamento.Length); j++) { _zeros += "0"; }
                importo_pagamento = _zeros + importo_pagamento;

                bool pagato = bool.Parse(data.GetValue("pagato").ToString());

                if (pagato)
                    codice += "3004" + descrPagamento_Length + descrPagamento + importo_pagamento + "\n";  //30048PRODOTTO000001000
                else
                    codice += "3005" + descrPagamento_Length + descrPagamento + importo_pagamento + "\n";

                //Riga opzione stamapa subtotale
                bool stampa_subtotale = bool.Parse(data.GetValue("stampa_subtotale").ToString());
                if (stampa_subtotale)
                    codice += "3003" + "\n";

                //Riga aggiuntiva
                string riga_aggiuntiva = data.GetValue("riga_aggiuntiva").ToString();
                string riga_aggiuntiva_Length = ((riga_aggiuntiva.Length >= 10) ? riga_aggiuntiva.Length.ToString() : ("0" + riga_aggiuntiva.Length.ToString()));

                if (!string.IsNullOrEmpty(riga_aggiuntiva))
                    codice += "3008" + "1" + riga_aggiuntiva_Length + riga_aggiuntiva + "\n";   //3008115RIGA AGGIUNTIVA


                codice += "3011\n";

                //Righe con descrizioni clienti
                string cliente="";
                try { cliente = data.GetValue("cliente").ToString(); } catch { }

                int cliente_Length = cliente.Length;

                codice += "3012" + "1" + "1 " + "\n";
                codice += "3012" + "1" + "32********************************" + "\n";

                if (cliente_Length > 32)
                {
                    string nome = cliente.Split(' ')[0];
                    if (!string.IsNullOrEmpty(nome))
                    {
                        int padCount = (32 - nome.Length) / 2;
                        int len = padCount + nome.Length;
                        string nomeLength = ((len >= 10) ? len.ToString() : ("0" + len.ToString()));

                        codice += "3012" + "1" + nomeLength + nome.PadLeft(len) + "\n";
                    }
                    string cognome = cliente.Split(' ')[1];
                    if (!string.IsNullOrEmpty(cognome))
                    {
                        int padCount = (32 - cognome.Length) / 2;
                        int len = padCount + cognome.Length;
                        string cognomeLength = ((len >= 10) ? len.ToString() : ("0" + len.ToString()));

                        codice += "3012" + "1" + cognomeLength + cognome.PadLeft(len) + "\n";
                    }
                }
                else
                {
                    string cliente_Lunghezza = ((cliente.Length >= 10) ? cliente.Length.ToString() : ("0" + cliente.Length.ToString()));

                    if (!string.IsNullOrEmpty(cliente)) {
                        int padCount = (32 - cliente.Length) / 2;
                        int len = padCount + cliente.Length;
                        cliente_Lunghezza = ((len >= 10) ? len.ToString() : ("0" + len.ToString()));
                        codice += "3012" + "1" + cliente_Lunghezza + cliente.PadLeft(len) + "\n";
                    }
                    
                }
                try
                {
                    //Righe con codice fiscale cliente
                    string codfisc_cliente = data.GetValue("codfisc_cliente").ToString();

                    if (!string.IsNullOrEmpty(codfisc_cliente))
                    {
                        int padCount = (32 - codfisc_cliente.Length) / 2;
                        int len = padCount + codfisc_cliente.Length;
                        string codfisc_cliente_Lunghezza = (len >= 10) ? len.ToString() : ("0" + len.ToString());
                        codice += "3012" + "1" + codfisc_cliente_Lunghezza + codfisc_cliente.PadLeft(len) + "\n";

                    }
                    else { 
                        //codice += "3008" + "1" + "25" + "        [CF NON INDICATO]" + "\n";
                        }
                }
                catch {
                    //codice += "3008" + "1" + "25" + "       [CF NON INDICATO]" + "\n";
                }

                string num_ricevuta_desc = "Ricevuta Sportcard N. " + _id.Split('|')[0];

                int padCount2 = (32 - num_ricevuta_desc.Length) / 2;
                int len2 = padCount2 + num_ricevuta_desc.Length;
                string num_ricevuta_desc_lunghezza = (len2 >= 10) ? len2.ToString() : ("0" + len2.ToString());

                codice += "3012" + "1" + "32********************************" + "\n";

                codice += "3012" + "1" + num_ricevuta_desc_lunghezza + num_ricevuta_desc.PadLeft(len2) + "\n";

                codice += "3013\n";

                break;
            case 3:
                data = JObject.Parse(myJson.GetValue("data").ToString());

                int tipo_documento = int.Parse(data.GetValue("tipo_documento").ToString());
                string totale_documento = data.GetValue("totale_documento").ToString().Replace(".", "");

                //Gestione formato dei decimali (50.55 = 5055)
                if (totale_documento.Contains(","))
                    totale_documento = totale_documento.Split(',')[0] + (totale_documento.Split(',')[1].Length == 2 ? totale_documento.Split(',')[1] : totale_documento.Split(',')[1] + "0");
                else
                    totale_documento = totale_documento + "00";

                _zeros = "";
                for (int j = 0; j < (9 - totale_documento.Length); j++)
                {
                    _zeros += "0";
                }
                totale_documento = _zeros + totale_documento;

                //Riga apertura altri documenti
                codice += "4001" + tipo_documento + "0" + totale_documento + "\n";  //lo 0 setta la copia fattura come disattivata mentre 1 l'attiva

                bool stampa_intestazione = bool.Parse(data.GetValue("stampa_intestazione").ToString());
                if (stampa_intestazione)
                    codice += "4002" + "\n";  //Riga opzione stampa intestatzione

                int count3 = data.GetValue("righe").Count();
                for (int i = 0; i < count3; i++)
                {
                    JObject riga3 = JObject.Parse(data.GetValue("righe")[i].ToString());
                    string descrizione3 = riga3.GetValue("descrizione").ToString();

                    if (descrizione3.StartsWith("[#") && descrizione3.EndsWith("#]"))
                    {
                        int _length = descrizione3.Length - 4; //tolgo i caratteri especiali dal conteggio
                        codice += "4003" + "F" + ((_length >= 10) ? _length.ToString() : ("0" + _length.ToString())) + descrizione3.Replace("[#", "").Replace("#]", "") + totale_documento + "\n";
                    }
                    else
                        codice += "4003" + "1" + ((descrizione3.Length >= 10) ? descrizione3.Length.ToString() : ("0" + descrizione3.Length.ToString())) + descrizione3 + "\n";
                }

                bool stampa_rag_soc = bool.Parse(data.GetValue("stampa_rag_soc").ToString());
                bool chiusura_doc_non_fiscale = bool.Parse(data.GetValue("chiusura_doc_non_fiscale").ToString());
                bool chiusura_doc_fattura = bool.Parse(data.GetValue("chiusura_doc_fattura").ToString());

                if (stampa_rag_soc)
                    codice += "4005" + "\n";
                if (chiusura_doc_non_fiscale)
                    codice += "4004" + "\n";
                if (chiusura_doc_fattura)
                    codice += "4006" + "\n";

                break;
            default:
                break;
        }
               
        if (debug == "true")
        {
            //command- tipo -  quantità - reparto - len  --  descrizione    --    importo -- ID IVA
            //codice += "3008" + "1" + "1 " + "\n";
            //codice += "3301" + "8" + "000000000" + "000" + "17" + "Annullo scontrino" + "000000000" + "00" + "\n";
        }


        string concorrenza = Send_command("1010");

        //bit that tells if the printer is printing
        char printing = concorrenza.ElementAt(8);

        if(printing == '0')
        {
            foreach (string command_line in codice.Split('\n'))
            {
                string result = Send_command(command_line);
            }
        }
        else
        {
            if (printing == '1')
               return "ERROR";
            else
                return concorrenza;
            
        }
        
        return "OK";
    }

    public string Send_command(string command)
    {
        string _protocollo = ConfigurationManager.AppSettings.Get("Protocollo");
        string _LogLevel = ConfigurationManager.AppSettings.Get("LogLevel");
        string _Encoding = ConfigurationManager.AppSettings.Get("Encoding");
        string _IP_printer = ConfigurationManager.AppSettings.Get("IP_printer");
        string _Port = ConfigurationManager.AppSettings.Get("Port");

        //string debug = _protocollo + " - " + _LogLevel + " - " + _Encoding + " - " + _IP_printer + " - " + _Port;

        try
        {
            comunicationElement.CurrentProtocol = (Custom.CeFCom.Enums.ProtocolTypeEnum)Enum.Parse(typeof(Custom.CeFCom.Enums.ProtocolTypeEnum), _protocollo);
            comunicationElement.LogLevel = (Custom.CeFCom.Enums.LogLevelEnum)Enum.Parse(typeof(Custom.CeFCom.Enums.LogLevelEnum), _LogLevel);
            comunicationElement.EncodingType = (Custom.CeFCom.PrinterCodePages.EncodingTypeEnum)Enum.Parse(typeof(Custom.CeFCom.PrinterCodePages.EncodingTypeEnum), _Encoding);
        }
        catch (Exception ex)
        {
            return ex.Message;
        }

        if (!string.IsNullOrEmpty(command) && command.Length >= 4)
        {
            string cmd = command.Substring(0, 4);
            string cmdResponse = string.Empty;
            int openCommandResult = int.MinValue;

            openCommandResult = comunicationElement.CEFOpenEth(_IP_printer, Convert.ToInt32(_Port));


            //WRITE, READ AND CLOSE ONLY IF OPEN METHOD IS OK
            if (openCommandResult == (int)Custom.CeFCom.Enums.ErrorListEnum.OPERATION_OK)
            {
                comunicationElement.CEFWrite(command);

                comunicationElement.CEFRead(cmd, out cmdResponse);

                comunicationElement.CEFClose();

                return cmdResponse;
            }
            return "Operation failed ";
        }
        else
            return "invalid command ";

    }

    public class info
    {
        public int tipo_operazione { get; set; }
        public data data { get; set; }
    }
    public class data
    {
        public int tipo_riga { get; set; }
        public List<righe> righe { get; set; }
        public string descr_pagamento { get; set; }
        public float importo_pagamento { get; set; }
        public bool pagato { get; set; }
        public bool stampa_subtotale { get; set; }
        public string riga_aggiuntiva { get; set; }

        // if tipo operazione = 3 

        public bool stampa_intestazione { get; set; }
        public float importo_tot { get; set; }
        public bool stampa_rag_soc { get; set; }
        public bool chiusura_doc_non_fiscale { get; set; }
        public bool chiusura_doc_fattura { get; set; }
    }
    public class righe
    {
        public int tipo_riga { get; set; }
        public string descrizione { get; set; }
        public double importo { get; set; }

    }

}