using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.Serialization;
using System.Runtime.InteropServices;
using System.IO;

namespace iSTP_DataProcessing
{
    public partial class iSTP_DataProcessingWnd : Form
    {
        private DataProcessing _Controller;
        private SPSscripts MyScripts = new SPSscripts();
        private int FilterFreq = 10;
        private int SPSwaittime = 30 * 60;
        private List<string> VirtualPath = new List<string>();
        private int DeciScaleUP = 8;
        private int DeciScaleDOWN = 10;
        private List<SPSscripts.Sets_t> MySets = new List<SPSscripts.Sets_t>();

        public iSTP_DataProcessingWnd()
        {
            InitializeComponent();
            TreeInit();
            TreeCompinit();

            this.textBoxSPSwaittime.Text = this.SPSwaittime.ToString();

            SPSmodeCheckBox.Enabled = true;
            treeViewSPS.Enabled = true;

            textBoxDeciScaleUP.Text = DeciScaleUP.ToString();
            textBoxDeciScaleDOWN.Text = DeciScaleDOWN.ToString();
        }

        private void TreeCompinit()
        {
            string[] _name = CompensatoryMode.GetBatchFilesNames;
            var _items = checkedListBox1.Items;
            foreach (string set in _name)
            {
                _items.Add(set);
            }
        }

        private void TreeInit()
        {
            foreach (SPSscripts.Sets_t set in SPSscripts.Sets)
            {
                string[] _name = set.name.Split(System.IO.Path.DirectorySeparatorChar);
                TreeNode _tn = new TreeNode(_name[_name.Length - 1]);

                foreach (SPSscripts.ExeInfo_t exe in set.scripts)
                {
                    HiddenCheckBoxTreeNode _tn1 = new HiddenCheckBoxTreeNode(exe.name);
                    _tn1.Checked = true;
                    foreach (string param in exe.parameters)
                    {
                        HiddenCheckBoxTreeNode _tn2 = new HiddenCheckBoxTreeNode(param);
                        _tn1.Nodes.Add(_tn2);
                    }
                    _tn.Nodes.Add(_tn1);
                }

                treeViewSPS.Nodes.Add(_tn);
            }
            //treeViewSPS.ExpandAll();     
        }

        private SPSscripts.Sets_t FindCheckSets()
        {
            int _res = 0;

            while (_res < treeViewSPS.Nodes.Count)
                if (!treeViewSPS.Nodes[_res].Checked)
                    _res++;
                else
                    break;

            if (SPSscripts.Sets.Count == 0)
                return new SPSscripts.Sets_t();

            if (_res >= SPSscripts.Sets.Count)
                _res = 0;

            return SPSscripts.Sets[_res];
        }

        public void setController(DataProcessing controller)
        {
            this._Controller = controller;
        }

        private void close_btn_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.OK;
        }

        public bool RawCSVRequested { get { return (this.RawLogCsvButton.Checked && !this.SPSmodeCheckBox.Checked); } }
        public bool RawHxRequested { get { return (this.RawLogHxButton.Checked && !this.SPSmodeCheckBox.Checked); } }
        public bool PerSensorLogRequested { get { return this.RawLogDataPerSensorButton.Checked; } }
        public bool SPSrequested { get { return this.SPSmodeCheckBox.Checked; } }
        public SPSscripts.Sets_t[] SPSset { get { return MySets.ToArray(); } }
        public bool CompensatoryRequested { get { return this.CompensatoryModeCheckBox.Checked; } }
        public string CompensationSelected { get { return this.checkedListBox1.Items[checkedListBox1.SelectedIndex].ToString(); } }
        public bool FiltrationRequested { get { return this.checkBoxFiltration.Checked; } }
        public bool DecimationRequested { get { return this.checkBoxDecimation.Checked; } }
        public int FilterFreqRequested { get { return FilterFreq; } }
        public bool KeepAliveRequested { get { return checkBoxKeepAliveHDD.Checked; } }
        public int GetSPStaskWaittime { get { return SPSwaittime; } }
        public bool VirtualSensRequested { get { return checkBoxVirtualSens.Checked; } }
        public List<string> VirtualSensPath { get { return VirtualPath; } }
        public int GetDeciScaleUP { get { return DeciScaleUP; } }
        public int GetDeciScaleDOWN { get { return DeciScaleDOWN; } }

        private void RawLogCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            if (RawLogCheckBox.Checked)
                SPSmodeCheckBox.Checked = false;
        }

        private void SPSmodeCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            if (SPSmodeCheckBox.Checked)
                RawLogCheckBox.Checked = false;
        }

        private void CompensatoryModeCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            if (!CompensatoryModeCheckBox.Checked)
            {
                checkedListBox1.Enabled = false;
            }
            else
            {
                checkedListBox1.Enabled = true;
            }
        }

        bool IsDigitsOnly(string str)
        {
            foreach (char c in str)
            {
                if (c < '0' || c > '9')
                    return false;
            }

            return true;
        }

        private void checkBoxFiltration_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBoxFiltration.Checked)
            {
                const string partialName = "Filter";

                DirectoryInfo hdDirectoryInWhichToSearch = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory);
                if (hdDirectoryInWhichToSearch.Exists)
                {
                    FileInfo[] filesInDir = hdDirectoryInWhichToSearch.GetFiles(string.Format("*{0}*.dll", partialName));

                    if (filesInDir.Length == 0)
                    {
                        MessageBox.Show(
                            "Cannot find *Filter*.dll",
                            "Error",
                            MessageBoxButtons.OK,
                            MessageBoxIcon.Error);
                        checkBoxFiltration.Checked = false;
                    }
                    else if (filesInDir.Length > 1)
                    {
                        MessageBox.Show(
                            "Finds more then one *Filter*.dll. Please choose only one file and delete another.",
                            "Error",
                            MessageBoxButtons.OK,
                            MessageBoxIcon.Error);
                        checkBoxFiltration.Checked = false;
                    }
                }
            }
        }

        private void textBoxCutOffFreq_KeyUp(object sender, KeyEventArgs e)
        {
            string s = ((TextBox)sender).Text;
            if (s == string.Empty)
                return;
            if (IsDigitsOnly(s))
            {
                FilterFreq = Convert.ToInt32(s);
            }
        }

        private void textBoxSPSwaittime_KeyUp(object sender, KeyEventArgs e)
        {
            string s = ((TextBox)sender).Text;
            if (s == string.Empty)
                return;
            if (IsDigitsOnly(s))
            {
                SPSwaittime = Convert.ToInt32(s);
            }
        }

        private void TestLoadButton_Click(object sender, EventArgs e)
        {
            VirtualPath = VirtualSensorProfile.FindAllVirtualCSV(Directory.GetCurrentDirectory());

            richTextBoxVirtualPaths.Text = string.Empty;
            this.checkBoxVirtualSens.Checked = false;

            foreach (string s in VirtualPath)
            {
                if (VirtualSensorProfile.CheckProfile(s))
                {
                    richTextBoxVirtualPaths.Text += s + Environment.NewLine;
                    this.checkBoxVirtualSens.Checked = true;
                }
            }
        }

        private void textBoxDeciScaleUP_KeyUp(object sender, KeyEventArgs e)
        {
            string s = ((TextBox)sender).Text;
            if (s == string.Empty)
                return;
            if (IsDigitsOnly(s))
            {
                DeciScaleUP = Convert.ToInt32(s);
            }
        }

        private void textBoxDeciScaleDOWN_KeyUp(object sender, KeyEventArgs e)
        {
            string s = ((TextBox)sender).Text;
            if (s == string.Empty)
                return;
            if (IsDigitsOnly(s))
            {
                DeciScaleDOWN = Convert.ToInt32(s);
            }
        }

        private void numericUpDownSPScounter_ValueChanged(object sender, EventArgs e)
        {
            MySets.Add(this.FindCheckSets());
        }

        private void iSTP_DataProcessingWnd_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (SPSmodeCheckBox.Checked)
            {
                MySets.Add(this.FindCheckSets());
            }
        }
    }

    public class HiddenCheckBoxTreeNode : TreeNode
    {
        public HiddenCheckBoxTreeNode() { }
        public HiddenCheckBoxTreeNode(string text) : base(text) { }
        public HiddenCheckBoxTreeNode(string text, TreeNode[] children) : base(text, children) { }
        public HiddenCheckBoxTreeNode(string text, int imageIndex, int selectedImageIndex) : base(text, imageIndex, selectedImageIndex) { }
        public HiddenCheckBoxTreeNode(string text, int imageIndex, int selectedImageIndex, TreeNode[] children) : base(text, imageIndex, selectedImageIndex, children) { }
        protected HiddenCheckBoxTreeNode(SerializationInfo serializationInfo, StreamingContext context) : base(serializationInfo, context) { }
    }

    public class MixedCheckBoxesTreeView : TreeView
    {
        /// <summary>
        /// Specifies the attributes of a node
        /// </summary>
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public struct TV_ITEM
        {
            public int Mask;
            public IntPtr ItemHandle;
            public int State;
            public int StateMask;
            public IntPtr TextPtr;
            public int TextMax;
            public int Image;
            public int SelectedImage;
            public int Children;
            public IntPtr LParam;
        }

        public const int TVIF_STATE = 0x8;
        public const int TVIS_STATEIMAGEMASK = 0xF000;

        public const int TVM_SETITEMA = 0x110d;
        public const int TVM_SETITEM = 0x110d;
        public const int TVM_SETITEMW = 0x113f;

        public const int TVM_GETITEM = 0x110C;

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr SendMessage(HandleRef hWnd, int msg, int wParam, ref TV_ITEM lParam);

        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);

            // trap TVM_SETITEM message
            if (m.Msg == TVM_SETITEM || m.Msg == TVM_SETITEMA || m.Msg == TVM_SETITEMW)
                // check if CheckBoxes are turned on
                if (CheckBoxes)
                {
                    // get information about the node
                    TV_ITEM tv_item = (TV_ITEM)m.GetLParam(typeof(TV_ITEM));
                    HideCheckBox(tv_item);
                }
        }

        protected void HideCheckBox(TV_ITEM tv_item)
        {
            if (tv_item.ItemHandle != IntPtr.Zero)
            {
                // get TreeNode-object, that corresponds to TV_ITEM-object
                TreeNode currentTN = TreeNode.FromHandle(this, tv_item.ItemHandle);

                HiddenCheckBoxTreeNode hiddenCheckBoxTreeNode = currentTN as HiddenCheckBoxTreeNode;
                // check if it's HiddenCheckBoxTreeNode and
                // if its checkbox already has been hidden

                if (hiddenCheckBoxTreeNode != null)
                {
                    HandleRef treeHandleRef = new HandleRef(this, Handle);

                    // check if checkbox already has been hidden
                    TV_ITEM currentTvItem = new TV_ITEM();
                    currentTvItem.ItemHandle = tv_item.ItemHandle;
                    currentTvItem.StateMask = TVIS_STATEIMAGEMASK;
                    currentTvItem.State = 0;

                    IntPtr res = SendMessage(treeHandleRef, TVM_GETITEM, 0, ref currentTvItem);
                    bool needToHide = res.ToInt32() > 0 && currentTvItem.State != 0;

                    if (needToHide)
                    {
                        // specify attributes to update
                        TV_ITEM updatedTvItem = new TV_ITEM();
                        updatedTvItem.ItemHandle = tv_item.ItemHandle;
                        updatedTvItem.Mask = TVIF_STATE;
                        updatedTvItem.StateMask = TVIS_STATEIMAGEMASK;
                        updatedTvItem.State = 0;

                        // send TVM_SETITEM message
                        SendMessage(treeHandleRef, TVM_SETITEM, 0, ref updatedTvItem);
                    }
                }
            }
        }

        protected override void OnBeforeCheck(TreeViewCancelEventArgs e)
        {
            base.OnBeforeCheck(e);

            // prevent checking/unchecking of HiddenCheckBoxTreeNode,
            // otherwise, we will have to repeat checkbox hiding
            if (e.Node is HiddenCheckBoxTreeNode)
                e.Cancel = true;
        }
    }
}
