using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace Nappat.CsCreator
{
    /// <summary>
    /// This class contains help methods for writing C# code.
    /// This methods are call from PartWriter.cs
    /// </summary>
    internal class PartWriterHelpMethods
    {
        #region Internal Methods
        //Return list of chars that set pins. Remove empty spaces.
        internal static List<string> PinSetMethod(string pinParserString)
        {
            char[] separators = new char[] { ' ' };
            return pinParserString.Split(separators, StringSplitOptions.RemoveEmptyEntries).ToList<string>();
        }
        //Return List of stings that are code lines.
        internal static List<string> ControlSwitchesWriter(List<string> controlSwitchesCurrent, List<string> controlSwitchesPast)
        {
            if (controlSwitchesCurrent.Count != PartWriter.ControlSwitchesName.Count)
                throw new Exception("Not correct count.");

            List<string> tempList = new List<string>();

            for (int i = 0; i < controlSwitchesCurrent.Count; i++)
            {
                if (controlSwitchesCurrent[i] != "1" && controlSwitchesCurrent[i] != "0")
                    throw new Exception("String" + " \"" + controlSwitchesCurrent[i] + "\" " + "is illegal.");

                else if (controlSwitchesCurrent[i] != controlSwitchesPast[i])
                {
                    if (controlSwitchesCurrent[i] == "1")
                    {
                        tempList.Add(PartWriter.IndentMethod() + "tc.DigitalOutputs.Set(" + "\"" + CsCreator.DeviceName + "\"" + ", " + "\"" + PartWriter.ControlSwitchesName[i] + "\"" + ", " + "DigitalValue.High);");
                    }
                    else if (controlSwitchesCurrent[i] == "0")
                    {
                        tempList.Add(PartWriter.IndentMethod() + "tc.DigitalOutputs.Set(" + "\"" + CsCreator.DeviceName + "\"" + ", " + "\"" + PartWriter.ControlSwitchesName[i] + "\"" + ", " + "DigitalValue.Low);");
                    }
                }
            }
            return tempList;
        }
        //Return List of stings that are code lines.
        internal static List<string> OutputSensorsWriter(List<string> outputSensorsSetCurrent, List<string> outputSensorsSetPast, int timeOutTime, string lineComment)
        {
            if (outputSensorsSetCurrent.Count != PartWriter.OutputSensorsName.Count)
                throw new Exception("Sensors array has not correct count.");

            List<string> retList = new List<string>();
            List<string> unlockPositions = new List<string>();
            Dictionary<string, string> setPositions = new Dictionary<string, string>();
            Dictionary<string, string> lockPositions = new Dictionary<string, string>();

            for (int i = 0; i < outputSensorsSetCurrent.Count; i++)
            {
                if (outputSensorsSetCurrent[i].ToLower() != "x" && outputSensorsSetCurrent[i] != "/" && outputSensorsSetCurrent[i] != "\\" && outputSensorsSetCurrent[i] != "1" && outputSensorsSetCurrent[i] != "0")
                    throw new Exception("String" + " \"" + outputSensorsSetCurrent[i] + "\" " + "is illegal.");

                if (outputSensorsSetCurrent[i] != outputSensorsSetPast[i])
                {
                    if (outputSensorsSetCurrent[i].ToLower() == "x")
                        unlockPositions.Add(outputSensorsSetCurrent[i]);
                    else if (outputSensorsSetCurrent[i] == "/" || outputSensorsSetCurrent[i] == "\\")
                        setPositions.Add(PartWriter.OutputSensorsName[i], outputSensorsSetCurrent[i]);
                    else if ((outputSensorsSetCurrent[i] == "0" || outputSensorsSetCurrent[i] == "1") && outputSensorsSetPast[i] == "x")
                        lockPositions.Add(PartWriter.OutputSensorsName[i], outputSensorsSetCurrent[i]);
                }
            }

            if (unlockPositions.Count > 0)
            {
                foreach (string pinName in unlockPositions)
                    retList.Add(PartWriter.IndentMethod() + "tc.UnlockInput(" + "\"" + CsCreator.DeviceName + "\"" + ", " + "\"" + pinName + "\"" + ");");
            }

            if (setPositions.Count == 0)
            {
                retList.Add(PartWriter.IndentMethod() + "Thread.Sleep(" + ((timeOutTime) * 10).ToString() + ");");
            }

            else if (setPositions.Count == 1)
            {
                foreach (string pinName in setPositions.Keys)
                {
                    if (setPositions[pinName] == "/")
                    {
                        retList.Add(PartWriter.IndentMethod() + "if (tc.WaitForChannelPattern(" + "\"" + CsCreator.DeviceName + "\"" + ", " + "\"" + pinName + "\"" + ", " + ((timeOutTime) * 10).ToString() + ", " + "DigitalValue.High) < 0)");
                        retList.Add(PartWriter.IndentMethod() + "{");
                        PartWriter.Indent++;
                        retList.Add(PartWriter.IndentMethod() + "tc.LogFatalError(" + "\"" + lineComment + "\"" + ");");
                        PartWriter.Indent--;
                        retList.Add(PartWriter.IndentMethod() + "}");
                    }
                    else if (setPositions[pinName] == "\\")
                    {
                        retList.Add(PartWriter.IndentMethod() + "if (tc.WaitForChannelPattern(" + "\"" + CsCreator.DeviceName + "\"" + ", " + "\"" + pinName + "\"" + ", " + ((timeOutTime) * 10).ToString() + ", " + "DigitalValue.Low) < 0)");
                        retList.Add(PartWriter.IndentMethod() + "{");
                        PartWriter.Indent++;
                        retList.Add(PartWriter.IndentMethod() + "tc.LogFatalError(" + "\"" + lineComment + "\"" + ");");
                        PartWriter.Indent--;
                        retList.Add(PartWriter.IndentMethod() + "}");
                    }
                }
            }

            else if (setPositions.Count > 1)
            {
                StringBuilder helpString = new StringBuilder();

                helpString.Append(PartWriter.IndentMethod() + "if (tc.WaitForPortPattern(" + "\"" + CsCreator.DeviceName + "\"" + ", " + "\"" + CsCreator.InBoardName + "\"" + ", " + ((timeOutTime) * 10).ToString() + ", new KeyValuePair<String, DigitalValue>[] {");

                foreach (string pinName in setPositions.Keys)
                {
                    if (setPositions[pinName] == "/")
                        helpString.Append(" new KeyValuePair<String, DigitalValue>(" + "\"" + pinName + "\"" + ", DigitalValue.High),");
                    else if (setPositions[pinName] == "\\")
                        helpString.Append(" new KeyValuePair<String, DigitalValue>(" + "\"" + pinName + "\"" + ", DigitalValue.Low),");
                }
                helpString.Remove(helpString.Length - 1, 1); //remove last ","
                helpString.Append("}) < 0)");
                retList.Add(helpString.ToString());
                retList.Add(PartWriter.IndentMethod() + "{");
                PartWriter.Indent++;
                retList.Add(PartWriter.IndentMethod() + "tc.LogFatalError(" + "\"" + lineComment + "\"" + ");");
                PartWriter.Indent--;
                retList.Add(PartWriter.IndentMethod() + "}");
            }

            if (lockPositions.Count > 0)
            {
                foreach (string pinName in lockPositions.Keys)
                {
                    if (lockPositions[pinName] == "1")
                        retList.Add(PartWriter.IndentMethod() + "tc.LockInput(" + "\"" + CsCreator.DeviceName + "\"" + ", " + "\"" + pinName + "\"" + ", DigitalValue.High, MessageSeverity.FatalError);");
                    else if (lockPositions[pinName] == "0")
                        retList.Add(PartWriter.IndentMethod() + "tc.LockInput(" + "\"" + CsCreator.DeviceName + "\"" + ", " + "\"" + pinName + "\"" + ", DigitalValue.Low, MessageSeverity.FatalError);");
                }
            }
            return retList;
        }
        internal static string EComMessageBuilderTX(string[] message, int start)
        {
            List<string> retMessage = new List<string>();
            retMessage.Add("new string[] {\"");
            retMessage.Add(message[start]);
            for (Int32 i = start + 1; i < message.Length; i++)
            {
                retMessage.Add(" " + message[i]);
            }
            retMessage.Add("\"}");

            retMessage[1].Trim();
            return string.Join(string.Empty, retMessage);
        }
        internal static string EComMessageBuilderRX(string[] message, int start)
        {
            List<string> retMessage = new List<string>();
            retMessage.Add("\"");
            retMessage.Add(message[start]);
            for (Int32 i = start + 1; i < message.Length; i++)
            {
                retMessage.Add(" " + message[i]);
            }
            retMessage.Add("\"");

            retMessage[1].Trim();
            return string.Join(string.Empty, retMessage);
        }
        internal static void TCGParser(string tcgPath)
        {
            StreamReader reader = File.OpenText(tcgPath);
            string line = null;

            while ((line = reader.ReadLine()) != null)
            {
                int firstChar = 0;

                if (line == "")
                    continue;

                for (int i = 0; i < line.Count(); i++)
                {
                    if (line[i] != ' ')
                    {
                        firstChar = i;
                        break;
                    }
                }
                if (line[firstChar] == '.')
                {
                    if (line[firstChar + 1].ToString().ToUpper() == "T")
                    {
                        char[] separators = new char[] { ' ', ':', ';' };
                        string[] tempStrings = line.Split(separators, StringSplitOptions.RemoveEmptyEntries);

                        PartWriter.TimeVariables.Add(tempStrings[1].Trim(), Convert.ToInt32(tempStrings[2].Trim()));
                    }
                }
            }
        }
        internal static int TimeSetter(string timeName)
        {
            int retTime = 0;

            if (PartWriter.TimeVariables.ContainsKey(timeName))
                retTime = PartWriter.TimeVariables[timeName];
            else
                try
                {
                    retTime = Convert.ToInt32(timeName);
                }
                catch
                {
                    throw new Exception("Can not found time variables: " + "'" + timeName + "'.");
                }
            return retTime;
        }
        #endregion
    }
}

