using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;


namespace DataProcessing
{
    public partial class FormHough : Form
    {
        public FormMain mainForm = null;
        
        public FormHough()
        {
            InitializeComponent();            
        }        

        public void Enable()
        {
            panelButtons.Enabled = true;
            panelReduction.Enabled = true;
            panelHough.Enabled = true;
            panelSurface.Enabled = true;
            panelSegmentation.Enabled = true;
        }

        public void Disable()
        {
            panelButtons.Enabled = false;
            panelReduction.Enabled = false;
            panelHough.Enabled = false;
            panelSurface.Enabled = false;
            panelSegmentation.Enabled = false;
        }

        public void UpdateValues()
        {
            if (mainForm.SelectedMesh != null)
            {
                if (mainForm.SelectedMesh.HoughVertices.Count < 1)
                {
                    labelVertices.Text = mainForm.SelectedMesh.Vertices.Count.ToString();
                }
                else
                {
                    labelVertices.Text = mainForm.SelectedMesh.HoughVertices.Count.ToString();
                }

                labelLines.Text = mainForm.SelectedMesh.Lines.Count.ToString();
                labelSurfaces.Text = mainForm.SelectedMesh.Surfaces.Count.ToString();
                labelSegments.Text = mainForm.SelectedMesh.Segments.Count.ToString();
            }
            else
            {
                labelVertices.Text = "0";
                labelLines.Text = "0";
                labelSurfaces.Text = "0";
                labelSegments.Text = "0";
            }
        }

        private void FormRotation_FormClosed(object sender, FormClosedEventArgs e)
        {
            mainForm.HoughForm = null;
        }        

        private void btnReduction_Click(object sender, EventArgs e)
        {
            if (mainForm.SelectedMesh != null)
            {
                if (comboBoxReductType.Text == "Octree")
                {
                    if (!backgroundWorker1.IsBusy)
                    {
                        mainForm.StartAction();
                        backgroundWorker1.RunWorkerAsync("octree");
                    }
                    else
                        MessageBox.Show("Action is still in progress... please wait.");
                }
                else if (comboBoxReductType.Text == "Constant Lenght")
                {
                    if (!backgroundWorker1.IsBusy)
                    {
                        mainForm.StartAction();
                        backgroundWorker1.RunWorkerAsync("lenght");
                    }
                    else
                        MessageBox.Show("Action is still in progress... please wait.");
                }
                else if (comboBoxReductType.Text == "None")
                {
                    mainForm.SelectedMesh.PointReduction("none", 0);
                    mainForm.ReDraw();
                }
            }            
        }

        private void btnDeleteReduction_Click(object sender, EventArgs e)
        {
            mainForm.SaveState();
            
            if (mainForm.SelectedMesh != null)
            {
                mainForm.SelectedMesh.DeleteReduction();
                mainForm.ReDraw();
                UpdateValues();
            }            
        }

        private void btnLine_Click(object sender, EventArgs e)
        {
            if (mainForm.SelectedMesh != null)
            {
                if (!backgroundWorker1.IsBusy)
                {
                    mainForm.StartAction();
                    backgroundWorker1.RunWorkerAsync("line");
                }
                else
                    MessageBox.Show("Action is still in progress... please wait.");
            }
        }

        private void btnDeleteLine_Click(object sender, EventArgs e)
        {
            mainForm.SaveState();
            
            if (mainForm.SelectedMesh != null)
            {
                mainForm.SelectedMesh.DeleteLines();
                mainForm.ReDraw();
                UpdateValues();
            }           
        }

        private void btnSurface_Click(object sender, EventArgs e)
        {
            if (mainForm.SelectedMesh != null)
            {
                if (!backgroundWorker1.IsBusy)
                {
                    mainForm.StartAction();
                    backgroundWorker1.RunWorkerAsync("surface");
                }
                else
                    MessageBox.Show("Action is still in progress... please wait.");
            }
        }

        private void btnDeleteSurface_Click(object sender, EventArgs e)
        {
            mainForm.SaveState();
            
            if (mainForm.SelectedMesh != null)
            {
                mainForm.SelectedMesh.DeleteSurfaces();
                mainForm.ReDraw();
                UpdateValues();
            }            
        }

        private void btnSegmentation_Click(object sender, EventArgs e)
        {
            if (mainForm.SelectedMesh != null)
            {
                if (!backgroundWorker1.IsBusy)
                {
                    mainForm.StartAction();
                    backgroundWorker1.RunWorkerAsync("segmentation");
                }
                else
                    MessageBox.Show("Action is still in progress... please wait.");
            }
        }

        private void btnDeleteSegmentation_Click(object sender, EventArgs e)
        {
            mainForm.SaveState();

            if (mainForm.SelectedMesh != null)
            {
                mainForm.SelectedMesh.DeleteSegments();
                mainForm.ReDraw();
                mainForm.UpdateValues();
            }            
        }

        private void btnHoughSegmentation_Click(object sender, EventArgs e)
        {            
            if (mainForm.SelectedMesh != null)
            {
                if (comboBoxReductType.Text == "Octree")
                {
                    if (!backgroundWorker1.IsBusy)
                    {
                        mainForm.StartAction();
                        backgroundWorker1.RunWorkerAsync("all octree");
                    }
                    else
                        MessageBox.Show("Action is still in progress... please wait.");
                }
                else if (comboBoxReductType.Text == "Constant Lenght")
                {
                    if (!backgroundWorker1.IsBusy)
                    {
                        mainForm.StartAction();
                        backgroundWorker1.RunWorkerAsync("all lenght");
                    }
                    else
                        MessageBox.Show("Action is still in progress... please wait.");
                }
                else if (comboBoxReductType.Text == "None")
                {
                    if (!backgroundWorker1.IsBusy)
                    {
                        mainForm.StartAction();
                        backgroundWorker1.RunWorkerAsync("all none");
                    }
                    else
                        MessageBox.Show("Action is still in progress... please wait.");
                }
            }
        }

        private void btnDeleteAll_Click(object sender, EventArgs e)
        {
            mainForm.SaveState();

            if (mainForm.SelectedMesh != null)
            {
                mainForm.SelectedMesh.DeleteReduction();
                mainForm.SelectedMesh.DeleteLines();
                mainForm.SelectedMesh.DeleteSurfaces();
                mainForm.SelectedMesh.DeleteSegments();
                mainForm.ReDraw();
                mainForm.UpdateValues();
            }            
        }
        
        //backgroundworker provadi vypocet napozadi (v jinem threadu)
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            string type = e.Argument as string;            

            if (type == "octree")
            {
                mainForm.SelectedMesh.PointReduction("octree", (int)numBoxReductParam.Value);
            }

            if (type == "lenght")
            {
                mainForm.SelectedMesh.PointReduction("lenght", (int)numBoxReductParam.Value);
            }

            if (type == "line")
            {
                int binSize = (int)numBoxHoughBin.Value;
                int angleStep = (int)numBoxHoughSteps.Value;
                float distance = (float)numBoxHoughDistance.Value;
                int points = (int)numBoxHoughPoints.Value;
                int lenght = (int)numBoxHoughLenght.Value;

                mainForm.SelectedMesh.Hough(binSize, angleStep, distance, points, lenght);
            }

            if (type == "surface")
            {
                int distance = (int)numBoxSurfDistance.Value;
                int minSize = (int)numBoxSurfaceSize.Value;
                mainForm.SelectedMesh.MakeSurfaces(distance, minSize);
            }

            if (type == "segmentation")
            {
                mainForm.SelectedMesh.ObjectSegmentation((int)numBoxTolerance.Value);
            }

            string[] allType = type.Split(' ');

            if (allType[0] == "all")
            {
                if (allType[1] == "octree")
                {
                    mainForm.SelectedMesh.PointReduction("octree", (int)numBoxReductParam.Value);
                }
                else if (allType[1] == "lenght")
                {
                    mainForm.SelectedMesh.PointReduction("lenght", (int)numBoxReductParam.Value);
                }
                else if (allType[1] == "none")
                {
                    mainForm.SelectedMesh.PointReduction("none", 0);
                }

                int binSize = (int)numBoxHoughBin.Value;
                int angleStep = (int)numBoxHoughSteps.Value;
                float distance = (float)numBoxHoughDistance.Value;
                int points = (int)numBoxHoughPoints.Value;
                int lenght = (int)numBoxHoughLenght.Value;

                mainForm.SelectedMesh.Hough(binSize, angleStep, distance, points, lenght);

                int surfDistance = (int)numBoxSurfDistance.Value;
                int minSize = (int)numBoxSurfaceSize.Value;
                mainForm.SelectedMesh.MakeSurfaces(surfDistance, minSize);

                mainForm.SelectedMesh.ObjectSegmentation((int)numBoxTolerance.Value);
            }
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            mainForm.StopAction();
            mainForm.ReDraw();
            UpdateValues();
        }

        private void comboBoxReductType_TextChanged(object sender, EventArgs e)
        {
            if (comboBoxReductType.Text == "Octree")
            {
                labelReductParam.Text = "Octree Depth:";
            }
            else
            {
                labelReductParam.Text = "Lenght:";
            }
        }

        ToolTip toolTipHough = new ToolTip();

        private void FormHough_Load(object sender, EventArgs e)
        {
            toolTipHough.SetToolTip(this.labelType, "Metoda redukce bodů.\r\nOctree - redukce pomocí oktalového stromu\r\nConstant Lenght - Bude dodržena minimální vzdálenost mezi sousedními body.");
            toolTipHough.SetToolTip(this.labelReductParam, "Hodnota parametru podle zvolené metody.\r\nMinimální vzdálenost mezi body je zadávána v cm.");
            toolTipHough.SetToolTip(this.btnReduction, "Spustí redukci bodů.");
            toolTipHough.SetToolTip(this.btnDeleteReduction, "Smaže redukci bodů.");
            toolTipHough.SetToolTip(this.labelMinLinePoints, "Minimální počet bodů na usečce.");
            toolTipHough.SetToolTip(this.labelMinLineLenght, "Minimální délka úsečky v cm.");
            toolTipHough.SetToolTip(this.labelMaxPointDistance, "Maximální vzdálenost mezi sousedními body v cm.");
            toolTipHough.SetToolTip(this.labelAngleStep, "Úhlový krok detekce useček. 1 - detekce po 1°, 10 - detekce po 10° stupních.\r\nVyšší hodnota znamená větší rychlost výpočtu a méně nalezených úseček.");
            toolTipHough.SetToolTip(this.labelBinSize, "Velikost jednoho pole Houghova zásobníku.\r\nVyšší hodnota detekuje více úseček a znamená rychlejší výpočet.");
            toolTipHough.SetToolTip(this.btnLine, "Spustí detekci úseček.");
            toolTipHough.SetToolTip(this.btnDeleteLine, "Smaže detekované úsečky.");
            toolTipHough.SetToolTip(this.labelLineDistance, "Maximální vzdálenost mezi koncovými body dvou useček pro vytvoření plochy.");
            toolTipHough.SetToolTip(this.labelSurfaceSize, "Minimální obsah plochy v cm^2.");
            toolTipHough.SetToolTip(this.btnSurface, "Spustí detekci ploch.");
            toolTipHough.SetToolTip(this.btnDeleteSurface, "Smaže detekované plochy.");
            toolTipHough.SetToolTip(this.btnSegmentation, "Spustí segmentaci.");
            toolTipHough.SetToolTip(this.btnDeleteSegmentation, "Smaže segmenty.");
            toolTipHough.SetToolTip(this.btnHoughSegmentation, "Spustí výpočet podle všech výše zadaných parametrů.");
            toolTipHough.SetToolTip(this.btnDeleteAll, "Smaže všechny detekované elementy.");
            toolTipHough.SetToolTip(this.labelTolerance, "Tolerance s jakou má větší objekt pojmout menší objekt.");

            toolTipHough.ShowAlways = true;
            toolTipHough.AutomaticDelay = 6000;
            toolTipHough.InitialDelay = 500;
        }
        
        //nutne kvuli bugu na winXP kdy se tooltip objevi pouze 1x
        private void labelType_MouseEnter(object sender, EventArgs e)
        {
            toolTipHough.Active = false;
            toolTipHough.Active = true;
        }

        private void labelReductParam_MouseEnter(object sender, EventArgs e)
        {
            toolTipHough.Active = false;
            toolTipHough.Active = true;
        }

        private void btnReduction_MouseEnter(object sender, EventArgs e)
        {
            toolTipHough.Active = false;
            toolTipHough.Active = true;
        }

        private void btnDeleteReduction_MouseEnter(object sender, EventArgs e)
        {
            toolTipHough.Active = false;
            toolTipHough.Active = true;
        }

        private void labelMinLinePoints_MouseEnter(object sender, EventArgs e)
        {
            toolTipHough.Active = false;
            toolTipHough.Active = true;
        }

        private void labelMinLineLenght_MouseEnter(object sender, EventArgs e)
        {
            toolTipHough.Active = false;
            toolTipHough.Active = true;
        }

        private void labelMinPointDistance_MouseEnter(object sender, EventArgs e)
        {
            toolTipHough.Active = false;
            toolTipHough.Active = true;
        }

        private void labelAngleStep_MouseEnter(object sender, EventArgs e)
        {
            toolTipHough.Active = false;
            toolTipHough.Active = true;
        }

        private void labelBinSize_MouseEnter(object sender, EventArgs e)
        {
            toolTipHough.Active = false;
            toolTipHough.Active = true;
        }

        private void btnLine_MouseEnter(object sender, EventArgs e)
        {
            toolTipHough.Active = false;
            toolTipHough.Active = true;
        }

        private void btnDeleteLine_MouseEnter(object sender, EventArgs e)
        {
            toolTipHough.Active = false;
            toolTipHough.Active = true;
        }

        private void labelLineDistance_MouseEnter(object sender, EventArgs e)
        {
            toolTipHough.Active = false;
            toolTipHough.Active = true;
        }

        private void labelSurfaceSize_MouseEnter(object sender, EventArgs e)
        {
            toolTipHough.Active = false;
            toolTipHough.Active = true;
        }

        private void btnSurface_MouseEnter(object sender, EventArgs e)
        {
            toolTipHough.Active = false;
            toolTipHough.Active = true;
        }

        private void btnDeleteSurface_MouseEnter(object sender, EventArgs e)
        {
            toolTipHough.Active = false;
            toolTipHough.Active = true;
        }

        private void btnSegmentation_MouseEnter(object sender, EventArgs e)
        {
            toolTipHough.Active = false;
            toolTipHough.Active = true;
        }

        private void btnDeleteSegmentation_MouseEnter(object sender, EventArgs e)
        {
            toolTipHough.Active = false;
            toolTipHough.Active = true;
        }

        private void btnHoughSegmentation_MouseEnter(object sender, EventArgs e)
        {
            toolTipHough.Active = false;
            toolTipHough.Active = true;
        }

        private void btnDeleteAll_MouseEnter(object sender, EventArgs e)
        {
            toolTipHough.Active = false;
            toolTipHough.Active = true;
        }

        private void FormHough_MouseEnter(object sender, EventArgs e)
        {
           // this.Activate();
           // this.Focus();
            
        }

        private void labelTolerance_MouseEnter(object sender, EventArgs e)
        {
            toolTipHough.Active = false;
            toolTipHough.Active = true;
        }
    }
}