using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using IpRangeToConfigConverter.Models;
using static C4IT.Logging.cLogManager;

using Microsoft.Win32;
using Excel = Microsoft.Office.Interop.Excel;
using C4IT.Logging;
using System.Xml.Serialization;

namespace IpRangeToConfigConverter
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        #region Properties


        #region SelectedFile

        public static readonly DependencyProperty SelectedFileProperty =
            DependencyProperty.Register("SelectedFile", typeof(string), typeof(MainWindow), new PropertyMetadata(""));

        public string SelectedFile
        {
            get { return (string)GetValue(SelectedFileProperty); }
            set { SetValue(SelectedFileProperty, value); }
        }

        #endregion

        private List<cSubnetDefinition> subnetDefinitions = new List<cSubnetDefinition>();
        private cSubnetXmlValues subnetXmlValues = new cSubnetXmlValues();

        private readonly Excel.Application excelApp = new Excel.Application();
        private Excel.Workbook excelWorkBook;

        #endregion

        public MainWindow()
        {
            InitializeComponent();
        }

        private bool SetWorkBook()
        {
            try
            {
                excelWorkBook = excelApp.Workbooks.Open(SelectedFile);
                return true;
            }
            catch (Exception E)
            {
                LogException(E);
            }

            return false;
        }

        private bool GetSubnetDefinitionsOutOfExcel()
        {
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);

            const int excelRowIndexOfFirstValue = 7;

            try
            {
                Excel.Worksheet firstWorkSheet = excelWorkBook.Worksheets.Cast<Excel.Worksheet>().First();
                Excel.Range range = firstWorkSheet.UsedRange;
                int excelRowCount = range.Rows.Count;


                for (int excelRow = excelRowIndexOfFirstValue; excelRow < excelRowCount; excelRow++)
                {
                    try
                    {
                        var tempSubnetDefinition = new cSubnetDefinition();

                        string cidrNotationValue = range.Cells[excelRow, 1].Value;
                        string lowerSubnetValue = range.Cells[excelRow, 2].Value;
                        string upperSubnetValue = range.Cells[excelRow, 3].Value;
                        string value = range.Cells[excelRow, 4].Value;
                        string connectionSpeed = range.Cells[excelRow, 5].Value;

                        if (value is null || (cidrNotationValue is null && (lowerSubnetValue is null || upperSubnetValue is null)))
                        {
                            LogEntry($"Definition in line {excelRow} is invalid.", LogLevels.Info);
                            continue;
                        }

                        if (string.IsNullOrEmpty(cidrNotationValue) == false)
                        {
                            var splitValues = cidrNotationValue.Split('/');

                            if (splitValues.Count() < 2)
                                continue;

                            tempSubnetDefinition.Subnet = splitValues[0];

                            if (int.TryParse(splitValues[1], out int subnetBits))
                                tempSubnetDefinition.SubnetBits = subnetBits;
                        }
                        else
                        {
                            tempSubnetDefinition.Subnet = lowerSubnetValue;
                            tempSubnetDefinition.UpperSubnet = upperSubnetValue;
                        }

                        tempSubnetDefinition.Value = value;
                        tempSubnetDefinition.ConnectionSpeed = connectionSpeed;

                        subnetDefinitions.Add(tempSubnetDefinition);
                    }
                    catch (Exception E)
                    {
                        LogException(E);
                    }
                }

                return true;
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                LogMethodEnd(CM);
            }

            return false;
        }

        private bool ParseSubnetValuesToXmlObject()
        {
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                foreach (var subnetDefinition in subnetDefinitions)
                {
                    subnetXmlValues.SubnetEntries.Add(new cSubnetXmlValues.cComputationSubnetEntry(subnetDefinition));

                    if (!string.IsNullOrEmpty(subnetDefinition.ConnectionSpeed))
                        subnetXmlValues.SubnetEnumerations.Add(new cSubnetXmlValues.cComputationEnumerationEntry(subnetDefinition));
                }

                return true;
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                LogMethodEnd(CM);
            }

            return false;
        }

        private void ConvertButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (!SetWorkBook())
                {
                    LogEntry($"Couldn't open Excel Workbook with path {SelectedFile}", LogLevels.Fatal);
                    return;
                }

                if (!GetSubnetDefinitionsOutOfExcel())
                {
                    LogEntry($"Couldn't parse excel values.", LogLevels.Fatal);
                    return;
                }

                if (!ParseSubnetValuesToXmlObject())
                {
                    LogEntry($"Couldn't parse processed excel values.", LogLevels.Fatal);
                    return;
                }

                using (var stringwriter = new System.IO.StringWriter())
                {
                    var serializer = new XmlSerializer(typeof(cSubnetXmlValues));
                    serializer.Serialize(stringwriter, subnetXmlValues);
                    OutputTextBox.Document.Blocks.Clear();
                    OutputTextBox.Document.Blocks.Add(new Paragraph(new Run(stringwriter.ToString())));
                }
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                excelWorkBook.Close();
                excelApp.Quit();
            }
        }

        private void SearchFileButton_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog
            {
                Filter = "Excel Files|*.xls;*.xlsx;*.xlsm"
            };
            if (openFileDialog.ShowDialog() == true)
                SelectedFile = openFileDialog.FileName;
        }
    }
}
