using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ImageBlockz.Api;
using ImageBlockz.Core;
using ImageBlockz.Operations.InOut;
using AForge;
using AForge.Imaging;
using AForge.Math;
using System.Reflection;
using System.Xml;
using ImageBlockz.Operations.Edit;
using ImageBlockz.Operations.Transformations;


namespace ImageBlockz.Gui
{
    public partial class MainWindow : Form
    {
        #region Fields

        private OperationDialog dialog   = new OperationDialog();
        private bool mainImageMaximized  = false;
        private History history          = new History();
        private int tabPagesLoadedCount  = 0;
        private string histogramType     = "red";
        private static Point mouseClick1 = new Point();
        private static Point mouseClick2 = new Point();

        #endregion

        #region Getters and Setters

        public Bitmap Image
        {
            get
            {
                return history.Current();
            }
            set
            {
                ChangedImage(value);
            }
        }

        public bool IsMainImageSet
        {
            get
            {
                return history.Counter() > 0;
            }
        }

        public OperationDialog EditDialog
        {
            get
            {
                return dialog;
            }
        }

        public ListViewTasks ConsoleBox
        {
            get
            {
                return listViewTasks1;
            }
        }

        PictureBox CurrentPictureBox
        {
            get
            {
                return (PictureBox)tabControlMainLeft.SelectedTab.Controls[0];
            }
        }

        Crownwood.Magic.Controls.TabPage CurrentTabPage
        {
            get
            {
                return tabControlMainLeft.SelectedTab;
            }
        }

        public Point MouseClick1
        {
            get
            {
                return mouseClick1;
            }
        }

        public Point MouseClick2
        {
            get
            {
                return mouseClick2;
            }
        }

        #endregion

        #region MainWindow constructor and events

        public MainWindow()
        {
            // Load all plugins in Plugins directory 
            PluginLoader.Load("ImageBlockz.Operations.dll");
            //PluginLoader.Load("Plugins/SamplePlugin.dll");
            FindPlugins();
            
            InitializeComponent();

            sequenceGui1.MainWindow = this;
            thumbnailBox.MainWindow = this;

            InitOnWindowLoad();
           
        }
        
        private void MainWindow_Load(object sender, EventArgs e)
        {
            //
            // Fill Main Menus
            //
            ControlFactory factory = ControlFactory.GetDefaultFactory();

            foreach (OperationInfo info in factory.OperationInfos)
            {
                if (info.MenuPath == null)
                {
                    continue;
                }

                OperationMenuItem operationItem = BuildMenuPath.BuildPath(info.MenuPath, info.OperationId, menuStrip);

                operationItem.Click += new EventHandler(this.toolStripMenuItem_Click);
            }
        }

        #endregion

        #region Zoom Operations

        private double GetZoomValue(PictureBox pictBox)
        {
            double zoom;

            if (pictBox.Width > pictBox.Height)
            {
                zoom = pictBox.Height / (double)pictBox.Image.Height;
            }
            else
            {
                zoom = pictBox.Width / (double)pictBox.Image.Width;
            }

            return zoom;
        }

        private void ZoomToValue(double value, PictureBox pictBox)
        {
            if (value > 50)
            {
                CurrentPictureBox.Width = (int)Math.Round(CurrentPictureBox.Image.Width * 50.0);
                CurrentPictureBox.Height = (int)Math.Round(CurrentPictureBox.Image.Height * 50.0);
                MessageBox.Show("Maximal Zoom reached.");
            }
            else if (value < 0.1)
            {
                CurrentPictureBox.Width = (int)Math.Round(CurrentPictureBox.Image.Width * 0.1);
                CurrentPictureBox.Height = (int)Math.Round(CurrentPictureBox.Image.Height * 0.1);
                MessageBox.Show("Minimal Zoom reached.");
            }
            else
            {
                CurrentPictureBox.Width = (int)Math.Round(CurrentPictureBox.Image.Width * value);
                CurrentPictureBox.Height = (int)Math.Round(CurrentPictureBox.Image.Height * value);
            }


            CalculateZoom(pictBox);
            SetPictureViewToThumbnailBox(CurrentPictureBox, CurrentTabPage);
        }

        private void ZoomIn(PictureBox pictBox)
        {
            ZoomToValue(2.0 * GetZoomValue(pictBox), pictBox);
        }

        private void ZoomOut(PictureBox pictBox)
        {
            ZoomToValue(0.5 * GetZoomValue(pictBox), pictBox);
        }

        private void ZoomInto(PictureBox pictureBox, Crownwood.Magic.Controls.TabPage tabPage)
        {
            double widthRatio = pictureBox.Width / tabPage.Width;
            double heightRatio = pictureBox.Height / tabPage.Height;

            if (heightRatio >= widthRatio)
            {
                pictureBox.Height = tabPage.Height;
                double width = (double)tabPage.Height / pictureBox.Image.Height * pictureBox.Image.Width;
                pictureBox.Width = (int)width;
            }
            else
            {
                pictureBox.Width = tabPage.Width;
                double height = (double)tabPage.Width / pictureBox.Image.Width * pictureBox.Image.Height;
                pictureBox.Height = (int)height;
            }

            CalculateZoom(pictureBox);
            SetPictureViewToThumbnailBox(pictureBox, tabPage);
        }

        private void ZoomToImage(PictureBox pictBox)
        {
            pictBox.Width = pictBox.Image.Width;
            pictBox.Height = pictBox.Image.Height;

            CalculateZoom(pictBox);
            SetPictureViewToThumbnailBox(pictBox, CurrentTabPage);
        }

        private void CalculateZoom(PictureBox pictBox)
        {
            double zoomRatio = GetZoomValue(pictBox);
            double zoomPercent = Math.Round(zoomRatio * 100);

            comboBoxZoom.Text = zoomPercent.ToString() + "%";
        }

        #endregion

        #region TabContolMain Events and Operations

        public void AddImageToTab(Bitmap bmp)
        {
            tabPagesLoadedCount++;
            Crownwood.Magic.Controls.TabPage tabPage = new Crownwood.Magic.Controls.TabPage("Export #" + tabPagesLoadedCount);
            
            PictureBox exportPictureBox = new PictureBox();
            exportPictureBox.Image = bmp;
            exportPictureBox.SizeMode = PictureBoxSizeMode.Zoom;

            tabPage.AutoScroll = true;
            tabPage.Controls.Add(exportPictureBox);
            tabPage.Scroll += new ScrollEventHandler(tabPageMainImageAndExport_Scroll);

            tabControlMainLeft.TabPages.Add(tabPage);

            ZoomInto(exportPictureBox, tabPage);
        }

        private void tabControlMainLeft_ClosePressed(object sender, EventArgs e)
        {
            if (tabControlMainLeft.SelectedTab == tabPageMainImage)
            {
                return;
            }
            else if (tabControlMainLeft.SelectedTab == tabPageBlockz)
            {
                return;
            }

            tabControlMainLeft.TabPages.Remove(tabControlMainLeft.SelectedTab);
        }

        private void tabControlMainLeft_SelectionChanged(object sender, EventArgs e)
        {
            if (tabControlMainLeft.SelectedTab == tabPageMainImage)
            {
                if (IsMainImageSet == false)
                {
                    InitOnWindowLoad();
                }
                else
                {
                    InitMainImageLayout();
                }
            }
            else if (tabControlMainLeft.SelectedTab == tabPageBlockz)
            {
                InitBlockzLayout();
            }
            else
            {
                InitExportLayout();
            }
        }

        private void tabControlMainLeft_Resize(object sender, EventArgs e)
        {
            if (CurrentTabPage == tabPageBlockz)
            {
                return;
            }

            SetPictureViewToThumbnailBox(CurrentPictureBox, CurrentTabPage);
        }

        private void SetPictureViewToThumbnailBox(PictureBox pictBox, Crownwood.Magic.Controls.TabPage tabPage)
        {
            Point location = new Point();

            location.X = -tabPage.AutoScrollPosition.X;
            location.Y = -tabPage.AutoScrollPosition.Y;

            thumbnailBox.SetPictureView(pictBox.Size, new Rectangle(location, tabPage.ClientSize));
        }

        private void tabPageMainImageAndExport_Scroll(object sender, ScrollEventArgs e)
        {
            SetPictureViewToThumbnailBox(CurrentPictureBox, CurrentTabPage);
        }

        #endregion

        #region MainMenu Strip

        private void openImageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenImageWithDialog();
        }

        private void saveImageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveImageWithDialog();
        }

        private void openSequenceToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenXmlWithDialog();
        }

        private void saveSequenceToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveXmlWithDialog();
        }

        private void exitProgramToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void copyImageToClipboardToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Clipboard.SetImage(CurrentPictureBox.Image);
        }

        private void pasteImageFromClipboardToolStripMenuItem_Click(object sender, EventArgs e)
        {
            System.Drawing.Imaging.PixelFormat format = System.Drawing.Imaging.PixelFormat.Format24bppRgb;

            Bitmap bmp = (Bitmap)Clipboard.GetImage();
            Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
            Image = bmp.Clone(rect, format);
        }

        private void undoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Undo();
        }

        private void verticalIntensityStatisticToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Analyse analyse = new Analyse();
            analyse.AnalyseType = "vertical";
            analyse.Do(history.Current());
        }

        private void horizontalIntensityStatisticToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Analyse analyse = new Analyse();
            analyse.AnalyseType = "horizontal";
            analyse.Do(history.Current());
        }

        private void toolStripMenuItem_Click(object sender, EventArgs e)
        {
            OperationMenuItem item = sender as OperationMenuItem;
            if (item == null)
            {
                return;
            }

            IOperation operation = OperationFactory.GetDefaultFactory().CreateOperation(item.OperationName);
            OperationControl control = ControlFactory.GetDefaultFactory().CreateControl(item.OperationName);

            if (control != null)
            {
                control.SetOperation(operation);
                control.IsNew = true;
                control.Bmp = history.Current();

                dialog.SetControl(control);
                dialog.ShowDialog();

                if (dialog.DialogResult == DialogResult.OK)
                {
                    Execute(operation);
                }
            }
            else
            {
                Execute(operation);
            }
        }

        #endregion

        #region MainImage ToolStrip

        private void btnMainImageOpen_Click(object sender, EventArgs e)
        {
            OpenImageWithDialog();
        }

        private void btnMainImageSave_Click(object sender, EventArgs e)
        {
            SaveImageWithDialog();
        }

        private void btnUndo_Click(object sender, EventArgs e)
        {
            Undo();
        }

        private void btnMainImageZoomIn_Click(object sender, EventArgs e)
        {
            ZoomIn(CurrentPictureBox);
        }

        private void btnMainImageZoomOut_Click(object sender, EventArgs e)
        {
            ZoomOut(CurrentPictureBox);
        }

        private void comboBoxZoom_SelectedIndexChanged(object sender, EventArgs e)
        {
            string str = comboBoxZoom.Items[comboBoxZoom.SelectedIndex].ToString();
            str = str.Remove(str.Length - 1);
            double result = 100;

            if (Double.TryParse(str, out result))
            {
                result = result / 100;

                ZoomToValue(result, CurrentPictureBox);
            }

            thumbnailBox.Update();
        }

        private void btnMainImageZoomInto_Click(object sender, EventArgs e)
        {
            ZoomInto(CurrentPictureBox, CurrentTabPage);
        }

        private void btnMainImageZoomOriginal_Click(object sender, EventArgs e)
        {
            ZoomToImage(CurrentPictureBox);
        }

        private void btnMainImageFullScreen_Click(object sender, EventArgs e)
        {
            if (mainImageMaximized == false)
            {
                tableLayout.ColumnStyles[1].Width = 0;
                tableLayout.RowStyles[1].Height = 0;

                mainImageMaximized = true;
            }
            else
            {
                tableLayout.ColumnStyles[1].Width = 200;
                tableLayout.RowStyles[1].Height = 100;

                mainImageMaximized = false;
            }
        }

        private void btnMainImageFlipHor_Click(object sender, EventArgs e)
        {
            Image.RotateFlip(RotateFlipType.RotateNoneFlipY);
            ChangedImage(Image);
        }

        private void btnMainImageFlipVer_Click(object sender, EventArgs e)
        {
            Image.RotateFlip(RotateFlipType.RotateNoneFlipX);
            ChangedImage(Image);
        }

        private void btnMainImageRotate_Click(object sender, EventArgs e)
        {
            Image.RotateFlip(RotateFlipType.Rotate90FlipNone);
            ChangedImage(Image);
        }

        private void btnClearTasks_Click(object sender, EventArgs e)
        {
            listViewTasks1.ClearAll();
        }

        private void btnRunDefault_Click(object sender, EventArgs e)
        {
            XmlDocument xmlMainImageDoc = new XmlDocument();

            try
            {
                xmlMainImageDoc.Load(Application.StartupPath + @"/Sequences/default.seq");
            }
            catch
            {
                MessageBox.Show("Default sequence not found in Sequence directory.");
                return;
            }

            Sequence mainImageSequence = new Sequence();

            mainImageSequence.FromXml(xmlMainImageDoc.DocumentElement);

            Bitmap bmp = null;

            listViewTasks1.AddRow("Default Sequence", "default.seq");

            foreach (IOperation oper in mainImageSequence.Operations)
            {
                if (oper is FromImage)
                {
                    ((FromImage)oper).Image = Image;
                }

                bmp = oper.Do(bmp);

                if (oper is ToImage)
                {
                    Image = ((ToImage)oper).Image;
                }
            }
        }

        private void btnToMainImage_Click(object sender, EventArgs e)
        {
            Image = (Bitmap)CurrentPictureBox.Image;
            ZoomInto(pictureBoxMain, tabPageMainImage);
        }

        private void btnToExport_Click(object sender, EventArgs e)
        {
            AddImageToTab((Bitmap)CurrentPictureBox.Image);
        }

        #endregion

        #region ImageBlockz ToolStrip

        private void btnSequenceRun_Click(object sender, EventArgs e)
        {
            RunSequence();
        }

        private void btnSequenceOpen_Click(object sender, EventArgs e)
        {
            OpenXmlWithDialog();
        }

        private void btnSequenceSave_Click(object sender, EventArgs e)
        {
            SaveXmlWithDialog();
        }

        private void btnSequenceClear_Click(object sender, EventArgs e)
        {
            sequenceGui1.ClearBlockz();
        }

        #endregion

        #region Open/Save with Dialog

        private void OpenImageWithDialog()
        {
            OpenFileDialog open = new OpenFileDialog();
            open.Filter = "JPG files (*.jpg)|*.jpg|PNG files (*.png)|*.png|BMP files (*.bmp)|*.bmp";

            if (DialogResult.OK == open.ShowDialog())
            {
                Bitmap openedBitmap;
                try
                {
                    openedBitmap = new Bitmap(open.FileName);
                    Rectangle rect = new Rectangle(0,0,openedBitmap.Width,openedBitmap.Height);
                    openedBitmap = openedBitmap.Clone(rect, System.Drawing.Imaging.PixelFormat.Format24bppRgb);                                     
                }
                catch (IOException)
                {
                    /*
                     * Here is the purpose exceptions were born for
                     */
                    MessageBox.Show("Program was unable to open specified file as image.");
                    return;
                }

                history.Clear();

                if (openedBitmap.PixelFormat == System.Drawing.Imaging.PixelFormat.Format8bppIndexed)
                {
                    AForge.Imaging.Filters.GrayscaleToRGB filter = new AForge.Imaging.Filters.GrayscaleToRGB();
                    Image = filter.Apply(openedBitmap);
                }
                else
                {
                    Image = openedBitmap;
                }

                ZoomInto(CurrentPictureBox, CurrentTabPage);
                /*
                 * Such things will be done in InitMainImageLayout or InitExportLayout
                 * 
                 * SetNewHistogram(CurrentPictureBox);
                 * SetPictureViewToThumbnailBox(CurrentPictureBox, CurrentTabPage);
                 */

                if (CurrentTabPage == tabPageMainImage)
                {
                    InitMainImageLayout();
                }
                else
                {
                    InitExportLayout();
                }
            }
        }

        private void SaveImageWithDialog()
        {
            SaveFileDialog save = new SaveFileDialog();
            save.Filter = "JPG files (*.jpg)|*.jpg";

            if (DialogResult.OK == save.ShowDialog())
            {
                CurrentPictureBox.Image.Save(save.FileName);
            }
        }

        private void OpenXmlWithDialog()
        {
            OpenFileDialog openXml = new OpenFileDialog();
            openXml.Filter = "SEQ files (*.seq)|*.seq";

            if (DialogResult.OK == openXml.ShowDialog())
            {
                XmlDocument xmlDoc = new XmlDocument();

                xmlDoc.Load(openXml.FileName);

                Sequence sequence = new Sequence();

                sequence.FromXml(xmlDoc.DocumentElement);

                sequenceGui1.Sequence = sequence;
            }
        }

        private void SaveXmlWithDialog()
        {
            SaveFileDialog saveXml = new SaveFileDialog();
            saveXml.Filter = "SEQ files (*.seq)|*.seq";
            Sequence sequence = sequenceGui1.Sequence;

            if (DialogResult.OK == saveXml.ShowDialog())
            {
                XmlDocument xmlDoc = new XmlDocument();

                XmlNode xmlNode = sequence.ToXml(xmlDoc);

                xmlDoc.AppendChild(xmlNode);

                xmlDoc.Save(saveXml.FileName);
            }
        }

        #endregion

        // Undo, IsNavigationInPreview, Changed Image, Execute, RunSequence, FindPlugins
        #region Base Operations

        private void Undo()
        {
            if (history.Counter() > 1)
            {
                history.Undo();                             
                pictureBoxMain.Image = history.Current();
                thumbnailBox.Image = history.Current();
                SetNewHistogram(pictureBoxMain);
                SetPictureViewToThumbnailBox(pictureBoxMain, tabPageMainImage);
            }

            if (history.Counter() < 2)
            {
                btnUndo.Enabled = false;
            }
        }

        private bool IsNavigationInPreview()
        {
            if (CurrentPictureBox.Size.Width > tabPageMainImage.Size.Width || CurrentPictureBox.Size.Height > tabPageMainImage.Size.Height)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private void ChangedImage(Bitmap newImage)
        {
            Bitmap bmp = (Bitmap)newImage.Clone();
            history.Add(bmp);
            
            pictureBoxMain.Image = history.Current();
            thumbnailBox.Image = history.Current();
            
            //ZoomInto(pictureBoxMain, tabPageMainImage);
            SetNewHistogram(pictureBoxMain);
            SetPictureViewToThumbnailBox(pictureBoxMain, tabPageMainImage);
        }

        private void Execute(IOperation operation)
        {
            Image = operation.Do(history.Current());

            btnUndo.Enabled = true;

            ConsoleBox.AddRow(operation.GetFormattedName(), operation.GetInfo());
        }

        private void RunSequence()
        {
            sequenceGui1.DoText();
        }

        private void FindPlugins()
        {
            string[] filePaths = Directory.GetFiles(@"Plugins", "*.dll");

            foreach (string fileName in filePaths)
            {
                PluginLoader.Load(fileName);
            }
        }

        #endregion

        #region Init Layouts

        private void InitMainImageLayout()
        {
            // MainImage ToolStrip
            toolStrip.Visible = true;
            toolStrip.Enabled = true;

            btnMainImageOpen.Visible = true;
            btnMainImageOpen.Enabled = true;

            btnMainImageSave.Visible = true;
            btnMainImageSave.Enabled = true;

            btnRunDefault.Visible = true;
            btnRunDefault.Enabled = true;

            btnUndo.Visible = true;
            btnUndo.Enabled = true;

            btnMainImageZoomIn.Enabled = true;
            btnMainImageZoomInto.Enabled = true;
            btnMainImageZoomOriginal.Enabled = true;
            btnMainImageZoomOut.Enabled = true;
            labelMainImageZoom.Enabled = true;

            btnMainImageFlipHor.Visible = true;
            btnMainImageFlipHor.Enabled = true;

            btnMainImageFlipVer.Visible = true;
            btnMainImageFlipVer.Enabled = true;

            btnMainImageRotate.Visible = true;
            btnMainImageRotate.Enabled = true;

            btnToExport.Visible = true;
            btnToExport.Enabled = true;

            btnToMainImage.Visible = false;
            btnToMainImage.Enabled = false;

            // ImageBlockz ToolStrip
            toolStripBlockz.Visible = false;
            toolStripBlockz.Enabled = false;

            // TabControl
            tabControlInfoRight.Enabled = true;

            // MainMenu Items
            openSequenceToolStripMenuItem.Enabled = false;
            saveSequenceToolStripMenuItem.Enabled = false;
            openImageToolStripMenuItem.Enabled = true;
            saveImageToolStripMenuItem.Enabled = true;
            editToolStripMenuItem.Enabled = true;
            imageToolStripMenuItem.Enabled = true;
            filtersToolStripMenuItem.Enabled = true;
            convolutionsToolStripMenuItem.Enabled = true;
            transformationsToolStripMenuItem.Enabled = true;
            analyseToolStripMenuItem.Enabled = true;
            pluginsToolStripMenuItem.Enabled = true;
            
            
            // Picture Box and Thumbnail
            pictureBoxMain.Visible = true;
            pictureBoxMain.Enabled = true;
            thumbnailBox.Image = CurrentPictureBox.Image;
            
            // Layout
            if (mainImageMaximized == false)
            {
                tableLayout.ColumnStyles[1].Width = 200;
            }

            if (CurrentPictureBox.Image != null)
            {
                CalculateZoom(CurrentPictureBox);
                SetPictureViewToThumbnailBox(CurrentPictureBox, CurrentTabPage);
                SetNewHistogram(CurrentPictureBox);
            }

            // Zoom ComboBox
            comboBoxZoom.Enabled = true;

            // Histogram
            histogramInfoRight.Enabled = true;
        }

        private void InitBlockzLayout()
        {
            // ImageBlockz ToolStrip
            toolStripBlockz.Visible = true;
            toolStripBlockz.Enabled = true;

            // MainImage ToolStrip
            toolStrip.Visible = false;
            toolStrip.Enabled = false;

            // MainMenu Items
            openImageToolStripMenuItem.Enabled = false;
            saveImageToolStripMenuItem.Enabled = false;
            openSequenceToolStripMenuItem.Enabled = true;
            saveSequenceToolStripMenuItem.Enabled = true;
            editToolStripMenuItem.Enabled = false;
            imageToolStripMenuItem.Enabled = false;
            filtersToolStripMenuItem.Enabled = false;
            convolutionsToolStripMenuItem.Enabled = false;
            transformationsToolStripMenuItem.Enabled = false;
            analyseToolStripMenuItem.Enabled = false;
            pluginsToolStripMenuItem.Enabled = false;
            

            // TabControl
            tabControlInfoRight.Enabled = false;

            // Layout
            tableLayout.ColumnStyles[1].Width = 0;

            // Histogram
            histogramInfoRight.Enabled = false;
        }

        private void InitExportLayout()
        {
            // MainImage ToolStrip
            toolStrip.Visible = true;
            toolStrip.Enabled = true;

            btnMainImageOpen.Visible = false;
            btnMainImageOpen.Enabled = false;
            btnMainImageSave.Visible = true;
            btnMainImageSave.Enabled = true;

            btnRunDefault.Visible = false;
            btnRunDefault.Enabled = false;

            btnUndo.Visible = false;
            btnUndo.Enabled = false;

            btnMainImageZoomIn.Enabled = true;
            btnMainImageZoomInto.Enabled = true;
            btnMainImageZoomOriginal.Enabled = true;
            btnMainImageZoomOut.Enabled = true;
            labelMainImageZoom.Enabled = true;

            btnMainImageFlipHor.Visible = false;
            btnMainImageFlipHor.Enabled = false;

            btnMainImageFlipVer.Visible = false;
            btnMainImageFlipVer.Enabled = false;

            btnMainImageRotate.Visible = false;
            btnMainImageRotate.Enabled = false;

            btnToExport.Visible = false;
            btnToExport.Enabled = false;

            btnToMainImage.Visible = true;
            btnToMainImage.Enabled = true;

            btnMainImageFlipHor.Visible = false;
            btnMainImageFlipHor.Enabled = false;

            btnMainImageFlipVer.Visible = false;
            btnMainImageFlipVer.Enabled = false;

            btnMainImageRotate.Visible = false;
            btnMainImageRotate.Enabled = false;

            // ImageBlockz ToolStrip
            toolStripBlockz.Visible = false;
            toolStripBlockz.Enabled = false;

            // TabControl
            tabControlInfoRight.Enabled = true;

            // MainMenu Items
            openSequenceToolStripMenuItem.Enabled = false;
            saveSequenceToolStripMenuItem.Enabled = false;
            openImageToolStripMenuItem.Enabled = false;
            saveImageToolStripMenuItem.Enabled = true;
            editToolStripMenuItem.Enabled = true;
            imageToolStripMenuItem.Enabled = false;
            filtersToolStripMenuItem.Enabled = false;
            convolutionsToolStripMenuItem.Enabled = false;
            transformationsToolStripMenuItem.Enabled = false;
            analyseToolStripMenuItem.Enabled = false;
            pluginsToolStripMenuItem.Enabled = false;
            

            // Thumbnail
            thumbnailBox.Image = CurrentPictureBox.Image;

            // Layout
            if (mainImageMaximized == false)
            {
                tableLayout.ColumnStyles[1].Width = 200;
            }

            // Zoom ComboBox
            comboBoxZoom.Enabled = true;

            CalculateZoom(CurrentPictureBox);
            SetPictureViewToThumbnailBox(CurrentPictureBox, CurrentTabPage);
            SetNewHistogram(CurrentPictureBox);
            
            // Histogram
            histogramInfoRight.Enabled = true;
        }

        private void InitOnWindowLoad()
        {
            // MainImage ToolStrip
            toolStrip.Visible = true;
            toolStrip.Enabled = true;

            btnMainImageOpen.Visible = true;
            btnMainImageOpen.Visible = true;

            btnMainImageOpen.Enabled = true;
            btnMainImageSave.Enabled = false;
            btnRunDefault.Enabled = false;
            btnMainImageZoomIn.Enabled = false;
            btnMainImageZoomInto.Enabled = false;
            btnMainImageZoomOriginal.Enabled = false;
            btnMainImageZoomOut.Enabled = false;
            labelMainImageZoom.Enabled = false;

            btnMainImageFlipHor.Visible = true;
            btnMainImageFlipHor.Enabled = false;

            btnMainImageFlipVer.Visible = true;
            btnMainImageFlipVer.Enabled = false;

            btnMainImageRotate.Visible = true;
            btnMainImageRotate.Enabled = false;

            btnToExport.Enabled = false;
            btnToMainImage.Visible = false;

            btnUndo.Visible = false;
            btnUndo.Enabled = false;

            btnToMainImage.Visible = true;
            btnToMainImage.Enabled = false;

            btnToExport.Visible = true;
            btnToExport.Enabled = false;

            // ImageBlockz ToolStrip
            toolStripBlockz.Visible = false;
            toolStripBlockz.Enabled = false;

            // TabControl
            tabControlInfoRight.Enabled = true;
            tableLayout.ColumnStyles[1].Width = 200;

            // MainMenu Items
            openSequenceToolStripMenuItem.Enabled = false;
            saveSequenceToolStripMenuItem.Enabled = false;
            openImageToolStripMenuItem.Enabled = true;
            saveImageToolStripMenuItem.Enabled = false;
            editToolStripMenuItem.Enabled = false;
            imageToolStripMenuItem.Enabled = false;
            filtersToolStripMenuItem.Enabled = false;
            convolutionsToolStripMenuItem.Enabled = false;
            transformationsToolStripMenuItem.Enabled = false;
            analyseToolStripMenuItem.Enabled = false;
            pluginsToolStripMenuItem.Enabled = false;
            
            // Zoom ComboBox
            comboBoxZoom.Enabled = false;

            // PictureBox
            pictureBoxMain.Visible = false;
            pictureBoxMain.Enabled = false;

            // Histogram
            histogramInfoRight.Enabled = false;
        }

        #endregion

        #region PictureBoxEvents

        private void pictureBoxMain_MouseMove(object sender, MouseEventArgs e)
        {
            double ratio = (double) CurrentPictureBox.Size.Width / CurrentPictureBox.Image.Size.Width;
            mouseLocationLabel.Text = "Mouse Location: " + (int)(e.X / ratio) + "," + (int)(e.Y / ratio);
        }

        private void pictureBoxMain_Click(object sender, EventArgs e)
        {
            double ratio = (double)CurrentPictureBox.Size.Width / CurrentPictureBox.Image.Size.Width;

            MouseEventArgs eTemp = (MouseEventArgs)e;
            mouseClick2 = mouseClick1;
            mouseClick1 = new Point((int)(eTemp.Location.X / ratio), (int)(eTemp.Location.Y / ratio));

            labelMouseClick1.Text = "Mouse Click 1: " + mouseClick1.X + "," + mouseClick1.Y;
            labelMouseClick2.Text = "Mouse Click 2: " + mouseClick2.X + "," + mouseClick2.Y;

            toolStripStatusColor.Text = Image.GetPixel(mouseClick1.X, mouseClick1.Y).ToString();

            double distance = GetClicksDistance();

            labelDistance.Text = "Distance: " + distance + "px";
        }

        private int GetClicksDistance()
        {
            int distance = (int)Math.Sqrt(Math.Pow(mouseClick1.X - mouseClick2.X, 2) + Math.Pow(mouseClick1.Y - mouseClick2.Y, 2));
            return distance;
        }

        #endregion

        #region Histogram Operations

        public void SetNewHistogram(PictureBox pictBox)
        {
            ImageStatistics stat = new ImageStatistics((Bitmap)pictBox.Image);

            Histogram hist = null;

            switch (histogramType)
            {
                case "red":
                    hist = stat.Red;
                    break;
                case "green":
                    hist = stat.Green;
                    break;
                case "blue":
                    hist = stat.Blue;
                    break;
                case "redWithoutBlack":
                    hist = stat.RedWithoutBlack;
                    break;
                case "greenWithoutBlack":
                    hist = stat.GreenWithoutBlack;
                    break;
                case "blueWithoutBlack":
                    hist = stat.BlueWithoutBlack;
                    break;
                default:
                    hist = stat.Red;
                    break;
            }

            histogramInfoRight.Values = hist.Values;
            histogramInfoRight.Update();
            propertyGrid.SelectedObject = hist;
        }

        private void histogramInfoRight_MouseClick(object sender, MouseEventArgs e)
        {
            contextMenuStripHistogram.Show(histogramInfoRight, e.Location);
        }

        private void redToolStripMenuItem_Click(object sender, EventArgs e)
        {
            histogramType = "red";
            SetNewHistogram(CurrentPictureBox);
        }

        private void greenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            histogramType = "green";
            SetNewHistogram(CurrentPictureBox);
        }

        private void blueToolStripMenuItem_Click(object sender, EventArgs e)
        {
            histogramType = "blue";
            SetNewHistogram(CurrentPictureBox);
        }

        private void redWithoutBlackToolStripMenuItem_Click(object sender, EventArgs e)
        {
            histogramType = "redWithoutBlack";
            SetNewHistogram(CurrentPictureBox);
        }

        private void greenWithoutBlackToolStripMenuItem_Click(object sender, EventArgs e)
        {
            histogramType = "greenWithoutBlack";
            SetNewHistogram(CurrentPictureBox);
        }

        private void blueWithoutBlackToolStripMenuItem_Click(object sender, EventArgs e)
        {
            histogramType = "blueWithoutBlack";
            SetNewHistogram(CurrentPictureBox);
        }

        #endregion

        private void thumbnailBox_NavigationEvent(object sender, NavigationEventArgs e)
        {

            if (IsNavigationInPreview())
            {
                tabControlMainLeft.SelectedTab.HorizontalScroll.Value = (int)Math.Round(e.RelativeLocation.X * CurrentPictureBox.Width);
                tabControlMainLeft.SelectedTab.VerticalScroll.Value = (int)Math.Round(e.RelativeLocation.Y * CurrentPictureBox.Height);

                tabControlMainLeft.SelectedTab.Update();
            }
        }

        private void crfaToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Bitmap newBmp = new Bitmap(Image);

            RadiusCrop radius = new RadiusCrop(mouseClick2, GetClicksDistance());

            newBmp = radius.Do(newBmp);
            
            CircularProjections circular = new CircularProjections();
            circular.AngleSamples = 720;
            circular.RadiusSamples = 1000;
            circular.Minimum = 0.4;
            circular.Maximum = 0.9;

            newBmp = circular.Do(newBmp);

            Analyse analyse = new Analyse();
            analyse.AnalyseType = "horizontal";
            Image = analyse.Do(newBmp);
        }

        private void userManualToolStripMenuItem_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Process.Start("UserManual.pdf");
        }

        private void pluginManualToolStripMenuItem_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Process.Start("PluginManual.pdf");
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            About about = new About();
            about.Show();
        }
    }
}
