using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Diagnostics;

namespace DxBlazorApplication2.AS400Kommunikation
{
    /// <summary>
    /// LaPoSocketHandler, der zusätzlich die Liste an Feldern hostet und
    /// mit nur einem bestimmten Programm auf der AS400 kommuniziert.
    /// </summary>
    public class AS400SocketSpecializedHandler : AS400SocketHandler
    {
        private List<AS400SocketField> feldListe;
        private string fehlerText = "";
        private bool handlerIstOk = false;

        public AS400SocketSpecializedHandler(string programm, List<AS400SocketField> feldListe, bool felderSenden, string sessionID)
            : base(new TcpClient("172.16.4.1", 5000))
        {
            this.feldListe = feldListe;
            //starten des Programms...
            String answer = this.ReadLine(); //OKASLAMBERTZ von AS400 
            this.WriteLine(programm);
            answer = this.ReadLine(); //OK von AS400
            if (answer.Substring(0, 2).Equals("FE"))
            {
                fehlerText = answer.Substring(2);
            }
            else
            {
                if (sessionID != null)
                {
                    //WICHTIG!!!! SessionID senden
                    this.WriteLine("00" + sessionID);
                }

                if (felderSenden)
                {
                    //Senden der Felder
                    foreach (AS400SocketField field in feldListe)
                    {
                        this.WriteLine(field.constructLine());
                    }
                }
                handlerIstOk = true;
            }
        }

        public AS400SocketSpecializedHandler(string programm, List<AS400SocketField> feldListe)
            : this(programm, feldListe, false, null)
        {

        }


        public void ChangeSatzArt(string satzArt)
        {
            foreach (AS400SocketField feld in feldListe)
            {
                feld.Satzart = satzArt;
            }
        }

        /// <summary>
        /// Zerlegt eine gelesene Zeile anhand der feldListe 
        /// in Einzelfelder
        /// Es sind immer Strings, nur die Formatierung ändert sich.
        /// </summary>
        /// <param name="line"></param>
        /// <param name="fields"></param>
        /// <returns></returns>
        public AS400PreviewContainer ToPreviewContainer(String line)
        {
            AS400PreviewContainer result;

            result = base.ToPreviewContainer(line, feldListe);

            return result;
        }

        public void WriteLine(AS400PreviewContainer container)
        {
            WriteLine(container, this.feldListe);
        }

        public void WriteLine(AS400PreviewContainer container, List<AS400SocketField> feldListe)
        {
            if (container.GetCount() != feldListe.Count)
            {
                throw new Exception("Falsche Anzahl an Feldern im LaPoSocketSpecializedHandler!");
            }
            else
            {
                StringBuilder line = new StringBuilder();

                line.Append(feldListe[0].Satzart.PadRight(2));

                for (int i = 0; i < feldListe.Count; i++)
                {
                    AS400SocketField feld = feldListe[i];
                    String value = container.GetField(i);

                    if (value.Length > feld.Length)
                    {
                        value = value.Substring(0, feld.Length);
                    }

                    line.Append(value.PadRight(feld.Length));
                }

                this.WriteLine(line.ToString());
            }
        }

        /// <summary>
        /// Die Feldinhalte werden anhand der Feldliste aufbereitet
        /// </summary>
        /// <param name="container"></param>
        /// <param name="feldListe"></param>
        public void WriteLineA(AS400PreviewContainer container, List<AS400SocketField> feldListe)
        {
            if (container.GetCount() != feldListe.Count)
            {
                throw new Exception("Falsche Anzahl an Feldern im LaPoSocketSpecializedHandler!");
            }
            else
            {
                StringBuilder line = new StringBuilder();

                line.Append(feldListe[0].Satzart.PadRight(2));

                for (int i = 0; i < feldListe.Count; i++)
                {
                    AS400SocketField feld = feldListe[i];
                    String value = container.GetField(i);

                    if (value == null)
                    {
                        value = "";
                    }

                    if (feld.Type == "S" || feld.Type == "P")
                    {
                        decimal wert = Convert.ToDecimal(value) * (decimal)Math.Pow(10, feld.InternalDecimalPlaces);
                        double temp = (double)Math.Round(wert, 0, MidpointRounding.AwayFromZero);

                        String token;
                        if (temp < 0)
                        {
                            token = reverseNegativeCheck(temp);
                        }
                        else
                        {
                            token = temp.ToString();
                        }
                        if (token.Length > feld.Length)
                        {
                            throw (new Exception(String.Format("Feldüberlauf {0} Wert {1}", feld.Name, value)));
                        }
                        line.Append(token.PadLeft(feld.Length, '0'));
                    }
                    else
                    {
                        if (value.Length > feld.Length)
                        {
                            value = value.Substring(0, feld.Length);
                        }
                        line.Append(value.PadRight(feld.Length));
                    }

                }
                this.WriteLine(line.ToString());

                //Console.WriteLine(line.ToString());
            }
        }

        public String reverseNegativeCheck(double zahl)
        {
            String result = Math.Abs(zahl).ToString();

            //Nachsehen nach letzter "Ziffer"
            String last = null;
            switch (result.Substring(result.Length - 1))
            {
                case "0":
                    last = "ü";
                    break;
                case "1":
                    last = "J";
                    break;
                case "2":
                    last = "K";
                    break;
                case "3":
                    last = "L";
                    break;
                case "4":
                    last = "M";
                    break;
                case "5":
                    last = "N";
                    break;
                case "6":
                    last = "O";
                    break;
                case "7":
                    last = "P";
                    break;
                case "8":
                    last = "Q";
                    break;
                case "9":
                    last = "R";
                    break;
            }

            result = result.Substring(0, result.Length - 1) + last;

            return result;
        }

        public void WriteLineDebug(AS400PreviewContainer container, List<AS400SocketField> feldListe)
        {
            if (container.GetCount() != feldListe.Count)
            {
                throw new Exception("Falsche Anzahl an Feldern im LaPoSocketSpecializedHandler!");
            }
            else
            {
                StringBuilder line = new StringBuilder();

                line.Append(feldListe[0].Satzart);

                for (int i = 0; i < feldListe.Count; i++)
                {
                    AS400SocketField feld = feldListe[i];
                    String value = container.GetField(i);

                    if (value.Length > feld.Length)
                    {
                        value = value.Substring(0, feld.Length);
                    }

                    line.Append(value.PadRight(feld.Length));
                }

                Console.WriteLine(line.ToString());
            }
        }

        public bool HandlerIstOk
        {
            get { return handlerIstOk; }
        }

        /// <summary>
        /// Meldet sich von der AS400 ab und schliesst den Socket
        /// </summary>
        public void closeConnection()
        {
            this.WriteLine("99");
            this.TcpClient.Close();
        }

        public string FehlerText
        {
            get
            {
                return fehlerText;
            }
        }
    }
}
