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.Text.RegularExpressions;
using System.Globalization;
using System.Resources;


namespace EduNetworkBuilder
{
    public partial class DeviceConfig : Form
    {
        NetworkComponent OriginalItem;
        NetworkComponent ClonedItem;
        bool processing = false;
        ToolTip mytooltips = new ToolTip();

        public DeviceConfig(NetworkComponent Original_Item)
        {
            InitializeComponent();
            LanguagifyComponents();
            OriginalItem = Original_Item;
            ClonedItem = NetworkComponent.Clone(OriginalItem);
            UpdateForm();
            lblHelp.Text = NB.Translate("DC_DeviceConfigEdit");
        }

        private void LoadFromOrig()
        {
            ClonedItem.UpdateFromComponent(OriginalItem);
        }

        private void LoadFromClone()
        {
            OriginalItem.UpdateFromComponent(ClonedItem);
        }

        private void LanguagifyComponents()
        {
            lblHostname.Text = NB.Translate("DC_lblHostname");
            lblHelp.Text = NB.Translate("DC_lblHelp");
            btnCancel.Text = NB.Translate("_Cancel");
            btnOK.Text = NB.Translate("_OK");
            btnIfAdd.Text = NB.Translate("DC_btnAdd");
            btnIfMinus.Text = NB.Translate("DC_btnMinus");
            btnIfEdit.Text = NB.Translate("_Edit");
            btnIfMinus.Text = NB.Translate("DC_btnMinus");
            btnIfAdd.Text = NB.Translate("DC_btnAdd");
            btnGateway.Text = NB.Translate("DC_btnGateway");
            btnRoutes.Text = NB.Translate("DC_btnRoutes");
            cbDHCP.Text = NB.Translate("DC_cbDHCP");
            btnDHCP.Text = NB.Translate("_DHCP");
            btnVLAN.Text = NB.Translate("DC_btnVLAN");
            btnFirewall.Text = NB.Translate("DC_btnFirewall");
            Text = NB.Translate("DC_Form");
        }


        private void UpdateForm()
        {
            Network theNet = NB.GetNetwork();
            if (theNet.ItemIsCritical(OriginalItem.hostname))
            {
                tbHostname.Enabled = false;
                mytooltips.SetToolTip(tbHostname, NB.Translate("DC_UpdateFormNoRename"));
            }
            if (processing) return;
            processing = true;
//            if (ClonedItem.GetType().ToString() == "EduNetworkBuilder.NetworkDevice")
            if(ClonedItem is NetworkDevice)
            {
                NetworkDevice ndCLonedItem = (NetworkDevice)ClonedItem;

                if (ndCLonedItem.DoesFirewall())
                    cbFirewall.Visible = true;
                else
                    cbFirewall.Visible = false;

                bool nicLocked = false;
                bool interfacesLocked = false;
                foreach (string nName in ndCLonedItem.NICNames())
                {
                    NetworkCard nic = ndCLonedItem.NicFromName(nName);
                    if (theNet.ItemIsLocked(ClonedItem.hostname, nic.NicName(), NetTestType.LockNic) ||
                                theNet.ItemIsLocked(ClonedItem.hostname, "", NetTestType.LockVLANsOnHost))
                    {
                        nicLocked = true;
                        interfacesLocked = true;
                    }
                }
                //if the selected interface is locked
                if (lbNics.SelectedIndex != -1 && theNet.ItemIsLocked(ClonedItem.hostname, StripNicName(lbNics.SelectedItem.ToString()), NetTestType.LockNicVLAN))
                {
                    nicLocked = true;
                    interfacesLocked = true;
                }
                cbFirewall.Checked = ndCLonedItem.HasAdvFirewall;
                if (ndCLonedItem.HasAdvFirewall && ndCLonedItem.DoesFirewall())
                    btnFirewall.Visible = true;
                else
                    btnFirewall.Visible = false;
                if (lbNics.SelectedIndex != -1)
                {
                    string nic_name = StripNicName(lbNics.SelectedItem.ToString());
                    NetworkCard nic = ndCLonedItem.NicFromName(nic_name);
                    if (nic != null)
                    {
                        if (nic.GetNicType == NicType.management_interface)
                            interfacesLocked = true;
                        if (nic.GetNicType == NicType.lo)
                            interfacesLocked = true;
                        if (nic.GetNicType == NicType.port)
                            interfacesLocked = true;
                        if (nic.GetNicType == NicType.wport)
                            interfacesLocked = true;
                        for (int i = 0; i < nic.IFCount; i++)
                        {
                            NetworkInterface nif = nic.GetInterface(i);
                            if (theNet.ItemIsLocked(ClonedItem.hostname, nif.nic_name, NetTestType.LockInterfaceVLAN) ||
                                theNet.ItemIsLocked(ClonedItem.hostname, nif.nic_name, NetTestType.LockVLANsOnHost))
                            {
                                nicLocked = true;
                                interfacesLocked = true;
                            }
                        }
                    }
                }
                if (interfacesLocked)
                {
                    btnIfAdd.Visible = false;
                    btnIfMinus.Visible = false;
                }
                else
                {
                    btnIfAdd.Visible = true;
                    btnIfMinus.Visible = true;
                }
                if (ndCLonedItem.CanAddNics && ! nicLocked)
                {
                    btnNicPlus.Visible = true;
                    btnNicMinus.Visible = true;
                }else
                {
                    btnNicPlus.Visible = false;
                    btnNicMinus.Visible = false;
                }

                if (ndCLonedItem.DoesVLANs() && theNet.VLANsEnabled)
                    btnVLAN.Visible = true;
                else btnVLAN.Visible = false;

                if(ndCLonedItem.CanServeDHCP)
                {
                    if (ndCLonedItem.GetIsDHCPServer())
                        cbDHCP.Checked = true;
                    cbDHCP.Visible = true;
                    if(cbDHCP.Checked)
                        btnDHCP.Visible = true;
                    else
                        btnDHCP.Visible = false;
                }
                else
                {
                    btnDHCP.Visible = false;
                    cbDHCP.Visible = false;
                }

                btnGateway.Visible = true;
                btnGateway.Text = string.Format(NB.Translate("DC_UdFrmGtewayStr"), ndCLonedItem.GetGateway().GetIP.ToIpString());                
                tbHostname.Text = ndCLonedItem.hostname;
                //Network cards are changed with the [edit] button and do not need to be updated here
                //IPAddresses are changed with the [edit] button and do not need to be updated here
               
                //The Nics
                int selectedLb = lbNics.SelectedIndex;
                lbNics.Items.Clear();
                List<string> lists = ndCLonedItem.NetworkCardStrings(false);
                foreach (string tstring in lists)
                {
                    lbNics.Items.Add(tstring);
                }
                if(selectedLb < 0)
                {
                    if (lbNics.Items.Count > 0)
                    {
                        lbNics.SelectedIndex = 0;
                        selectedLb = 0;
                    }
                }
                else
                {
                    if (selectedLb >= lbNics.Items.Count) selectedLb = -1;
                    lbNics.SelectedIndex = selectedLb;
                }

                if (lbNics.SelectedIndex >= 0)
                {
                    btnNicEdit.Enabled = true;
                    btnNicMinus.Enabled = true;
                }
                else
                {
                    btnNicEdit.Enabled = false;
                    btnNicMinus.Enabled = false;
                }

                lbArpTable.Items.Clear();
                lbArpTable.Items.Add("Arp Table MAC\tIPAddress\tIF");
                foreach(ArpEntry ae in ndCLonedItem.GetArps())
                {
                    lbArpTable.Items.Add(ae.MACAddress + "\t" + ae.IPAddr + "\t" + ae.NicOnWhichItIsFound.NicName);
                }

                //The IP Addresses for the given nic               
                //Use the index of the nic
                string selectedNicName = "";
                if (lbNics.SelectedItem != null) selectedNicName = lbNics.SelectedItem.ToString();
                //selectedNicName = Regex.Replace(selectedNicName, " .*", "");
                //selectedNicName = Regex.Replace(selectedNicName, "\\*", "");
                selectedNicName = StripNicName(selectedNicName);
                lists = ndCLonedItem.NetworkCardInterfaceStrings(selectedNicName);
                //get the IPAddress string list from the nic
                selectedLb = lbAddresses.SelectedIndex;
                lbAddresses.Items.Clear();
                foreach (string tstring in lists)
                {
                    lbAddresses.Items.Add(tstring);
                }
                if (selectedLb < 0)
                {
                    if (lbAddresses.Items.Count > 0)
                        lbAddresses.SelectedIndex = 0;
                }
                else
                {
                    if (lbAddresses.Items.Count > 0 && selectedLb < lbAddresses.Items.Count)
                     lbAddresses.SelectedIndex = selectedLb;
                }
                if (lbNics.SelectedIndex >= 0)
                {
                    btnIfEdit.Enabled = true;
                    btnIfMinus.Enabled = true;
                }
                else
                {
                    btnIfEdit.Enabled = false;
                    btnIfMinus.Enabled = false;
                }

            }
            processing = false;
        }

        private void StoreInCloneFromForm()
        {
            if(NB.GetComponentType(ClonedItem) == GeneralComponentType.device)
            {
                NetworkDevice ndCLonedItem = (NetworkDevice)ClonedItem;
                ndCLonedItem.hostname = tbHostname.Text;
                //Network cards are changed with the [edit] button and do not need to be updated here
                //IPAddresses are changed with the [edit] button and do not need to be updated here
            }
        }

        private void tbHostname_Validating(object sender, CancelEventArgs e)
        {
            //Make sure something else does not already have this hostname
            Network theNet = NB.GetNetwork();
            string otext;
            if(theNet.ItemIsCritical(tbHostname.Text))
            {
                if(tbHostname.Text != OriginalItem.hostname)
                {
                    e.Cancel = true;
                    otext = tbHostname.Text;
                    tbHostname.Text = OriginalItem.hostname;

                    MessageBox.Show(string.Format(NB.Translate("DC_HostValidateStr"), otext));
                }
            }
        }

        private void btnNicPlus_Click(object sender, EventArgs e)
        {
            List<NicType> WhatToAdd = new List<NicType>();
            Network tnet = NB.GetNetwork();
            NetworkCard tnic = null;
            //generate a new nic and add it to the device
            if (ClonedItem.GetType().ToString() == "EduNetworkBuilder.NetworkDevice")
            {
                NetworkDevice ndCLonedItem = (NetworkDevice)ClonedItem;
                if (!ndCLonedItem.CanAddNics) return;
                if(ndCLonedItem.GetNetType() == NetworkComponentType.firewall)
                {
                    WhatToAdd.Add(NicType.eth);
                    WhatToAdd.Add(NicType.tun);
                    WhatToAdd.Add(NicType.vpn);
                }
                if (ndCLonedItem.GetNetType() == NetworkComponentType.net_hub || ndCLonedItem.GetNetType() == NetworkComponentType.net_switch)
                {
                    WhatToAdd.Add(NicType.port);
                }
                if (ndCLonedItem.GetNetType() == NetworkComponentType.router )
                {
                    WhatToAdd.Add(NicType.eth);
                }
                if (ndCLonedItem.GetNetType() == NetworkComponentType.pc && ndCLonedItem.CountNics(NicType.eth) < 1)
                {
                    WhatToAdd.Add(NicType.eth);
                }
                if (WhatToAdd.Count == 1)
                {
                    tnic = ndCLonedItem.AddNic(WhatToAdd[0]);
                }
                if(WhatToAdd.Count > 1)
                {
                    //we need to choose a type:
                    Form QuestionForm = new Form();
                    QuestionForm.Text = NB.Translate("DC_UpdateFormAdd");
                    QuestionForm.Icon = Properties.Resources.NBIco;

                    Label lblText = new Label();
                    lblText.Location = new Point(5, 5);
                    lblText.Text = NB.Translate("DC_UpdateFormChoose:");

                    ComboBox cbQuestions = new ComboBox();
                    cbQuestions.Location = new Point(lblText.Location.X + lblText.Width + 5, lblText.Location.Y);
                    cbQuestions.Width = 60;
                    foreach(NicType nt in WhatToAdd)
                    {
                        cbQuestions.Items.Add(nt.ToString());
                    }
                    cbQuestions.SelectedIndex = 0;

                    QuestionForm.Width = cbQuestions.Location.X + cbQuestions.Width + 70;
                    QuestionForm.Height = 90;
                    QuestionForm.AutoSize = true;

                    Button btnAccept = new Button();
                    btnAccept.Location = new Point(cbQuestions.Location.X, cbQuestions.Location.Y + cbQuestions.Height + 10);
                    btnAccept.Text = NB.Translate("_Add");
                    btnAccept.Click += (s, g) => { Button b = (Button)s; Form f = (Form)b.Parent; f.Close(); };

                    QuestionForm.Controls.Add(lblText);
                    QuestionForm.Controls.Add(cbQuestions);
                    QuestionForm.Controls.Add(btnAccept);

                    QuestionForm.ShowDialog();
                    if(cbQuestions.SelectedIndex >=0)
                    {
                        tnic = ndCLonedItem.AddNic(WhatToAdd[cbQuestions.SelectedIndex]);
                    }
                }
                if(tnet != null)
                    tnet.RegisterNICAdded(ndCLonedItem.hostname, tnic.NicName());
            }
            UpdateForm();
        }

        private void btnNicMinus_Click(object sender, EventArgs e)
        {
            //delete the specified nic
            if (ClonedItem.GetType().ToString() == "EduNetworkBuilder.NetworkDevice")
            {
                NetworkDevice ndCLonedItem = (NetworkDevice)ClonedItem;
                ndCLonedItem.DeleteNic(lbNics.SelectedIndex + 1); //Skip the loopback nic
                UpdateForm();
            }
        }

        private void btnNicEdit_Click(object sender, EventArgs e)
        {
            //open a window to change the settings on the nic
            if (NB.GetComponentType(ClonedItem)  == GeneralComponentType.device)
            {
                NetworkDevice ndCLonedItem = (NetworkDevice)ClonedItem;
                ndCLonedItem.EditNic(lbNics.SelectedIndex +1); //Skip the loopback nic
                UpdateForm();
            }
        }

        private void btnIfAdd_Click(object sender, EventArgs e)
        {
            if (NB.GetComponentType(ClonedItem) == GeneralComponentType.device)
            {
                NetworkDevice ND = (NetworkDevice)ClonedItem;
                ND.AddNicInterface(lbNics.SelectedIndex + 1); //we do not show loopback
            }
            UpdateForm();
        }

        private void btnIfMinus_Click(object sender, EventArgs e)
        {
            //if one is selected and there are more than one, delete it
            if(lbAddresses.SelectedIndex >= 0)
            {
                if (lbAddresses.Items.Count > 1)
                {
                    //we can delete it
                    if(NB.GetComponentType(ClonedItem) == GeneralComponentType.device)
                    {
                        NetworkDevice ND = (NetworkDevice)ClonedItem;
                        ND.DeleteNicInterface(lbNics.SelectedIndex + 1, lbAddresses.SelectedIndex);
                    }
                }
                else
                    MessageBox.Show(NB.Translate("DC_UpdateFormNoDel"));
            }
            else
                MessageBox.Show(NB.Translate("DC_UpdateFormSelectDel"));
            UpdateForm();
        }

        private string StripNicName(string NIC)
        {
            string processed = NIC;
            processed = Regex.Replace(processed, " .*", "");
            processed = Regex.Replace(processed, "\\*", "");
            return processed;
        }

        private void editInterface()
        {
            if (ClonedItem.GetType().ToString() == "EduNetworkBuilder.NetworkDevice")
            {
                NetworkDevice ndCLonedItem = (NetworkDevice)ClonedItem;
                if (lbAddresses.SelectedIndex >= 0 && lbNics.SelectedIndex >= 0)
                {
                    string selectedNIC = StripNicName( lbNics.SelectedItem.ToString());
                    //selectedNIC = Regex.Replace(selectedNIC, " .*", "");
                    //selectedNIC = Regex.Replace(selectedNIC, "\\*", "");

                    ndCLonedItem.EditNicInterface(selectedNIC, lbAddresses.SelectedIndex, this);
                    UpdateForm();
                }
            }
        }

        private void btnIfEdit_Click(object sender, EventArgs e)
        {
            editInterface();
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            //we should prompt to save if we made changes
            Close();
        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            StoreInCloneFromForm();
            LoadFromClone(); //this saves the values in the object we passed it
            OriginalItem.IsDirty = true; //re-draw it
            Close();
        }

        private void lbNics_SelectedIndexChanged(object sender, EventArgs e)
        {
            UpdateForm();
            processing = false;
        }

        private void lbAddresses_DoubleClick(object sender, EventArgs e)
        {
            if(lbAddresses.SelectedIndex >=0)
            {
                //We have one to edit
                editInterface();
                UpdateForm();
            }
        }

        private void lbNics_DoubleClick(object sender, EventArgs e)
        {
            btnNicEdit_Click(sender,e); //We want this code in just one location
        }

        private void btnGateway_Click(object sender, EventArgs e)
        {
            if (NB.GetComponentType(ClonedItem) == GeneralComponentType.device)
            {
                NetworkDevice nd = (NetworkDevice)ClonedItem;
                if (nd.HasDHCPNic())
                {
                    MessageBox.Show(NB.Translate("DC_CannotEditGateway_DHCP"));
                }
                else
                {
                    nd.EditGateway(this);
                    UpdateForm();
                }
            }
        }

        private void btnRoutes_Click(object sender, EventArgs e)
        {
            if (ClonedItem == null) return;
            if (NB.GetComponentType(ClonedItem) == GeneralComponentType.link) return;
            NetworkDevice tItem = (NetworkDevice)ClonedItem;
            ListBoxWindow lbwindow = new ListBoxWindow(tItem,LBContents.routes);
            lbwindow.ShowDialog();
        }

        private void btnDHCP_Click(object sender, EventArgs e)
        {
            if (ClonedItem == null) return;
            if (NB.GetComponentType(ClonedItem) == GeneralComponentType.link) return;
            NetworkDevice tItem = (NetworkDevice)ClonedItem;
            ListBoxWindow lbwindow = new ListBoxWindow(tItem, LBContents.dhcp);
            lbwindow.ShowDialog();
        }


        private void cbDHCP_CheckedChanged(object sender, EventArgs e)
        {
            if(NB.GetComponentType(ClonedItem) == GeneralComponentType.device)
            {
                NetworkDevice ndClonedItem = (NetworkDevice)ClonedItem;
                ndClonedItem.SetDHCPServer(cbDHCP.Checked);
            }
            UpdateForm();
        }

        private void btnVLAN_Click(object sender, EventArgs e)
        {
            VLANConfig VLC = new VLANConfig((NetworkDevice)ClonedItem);
            VLC.ShowDialog();
        }

        private void btnFirewall_Click(object sender, EventArgs e)
        {
            //Open a firewall editing window.
            if (ClonedItem is NetworkDevice)
            {
                FirewallEditor FEditor = new FirewallEditor((NetworkDevice)ClonedItem);
                FEditor.ShowDialog();
            }
        }

        private void cbFirewall_CheckedChanged(object sender, EventArgs e)
        {
            if (NB.GetComponentType(ClonedItem) == GeneralComponentType.device)
            {
                NetworkDevice ndClonedItem = (NetworkDevice)ClonedItem;
                ndClonedItem.SetAdvFirewall(cbFirewall.Checked);
            }
            UpdateForm();
        }

        private void DeviceConfig_Shown(object sender, EventArgs e)
        {
            BuilderWindow BW = NB.GetBuilderWin();
            if(BW != null)
            {
                Point tLocation = new Point(BW.Location.X + ((BW.Width - Width) / 2), BW.Location.Y + ((BW.Height - Height) / 2));
                Location = tLocation;
            }
        }
    }
}