using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using DevExpress.XtraBars;
using DevExpress.XtraBars.Docking;
using DevExpress.XtraEditors;
using DevExpress.XtraTab;
using DevExpress.XtraTab.ViewInfo;
using PXP.Crawler.API.Designers.Controls;
using PXP.Crawler.API.Model;
using PXP.Crawler.API.Utils;

namespace PXP.Crawler.Forms.Edit
{
    public partial class ProjectXtraForm : EditXtraForm
    {
        #region Variables

        internal Project project;
        internal Control explorerControl;

        #endregion

        #region Constructor

        public ProjectXtraForm()
        {
            InitializeComponent();

            project = new Project();
            Text = project.Name;
            nameTextEdit.Text = project.Name;
            projectDesignerControl.Project = project;
            explorerControl = projectDesignerControl;
            projectDesignerControl.Visible = false;            
            explorerControl.Parent.Controls.Remove(explorerControl); 
            Program.mainForm.explorerDockPanel.Controls.Add(explorerControl);
            explorerControl.Dock = DockStyle.Fill;
            explorerControl.Visible = false;
            Program.mainForm.nodesTreePanel.Visible = false;
            project.RootProjectItem.Changed += RootProjectItem_Changed;

           InitProject();
        }

        public ProjectXtraForm(Project project)
        {
            InitializeComponent();

            this.project = project;
            Text = project.Name;
            nameTextEdit.Text = project.Name;
            projectDesignerControl.Project = project;
            explorerControl = projectDesignerControl;
            projectDesignerControl.Visible = false;
            explorerControl.Parent.Controls.Remove(explorerControl);
            Program.mainForm.explorerDockPanel.Controls.Add(explorerControl);
            explorerControl.Dock = DockStyle.Fill; 
            explorerControl.Visible = false;
            Program.mainForm.nodesTreePanel.Visible = false;
            project.RootProjectItem.Changed += RootProjectItem_Changed;

            InitProject();
        }

        private void InitProject()
        {
             project.LogMessage += project_LogMessage;
            if (!DesignMode)
                project.ExternalSettings = Program.sett;


        }

        void RootProjectItem_Changed(object sender, API.Utils.ListEx<ProjectItem>.ListExItemEventArgs<ProjectItem> e)
        {
            if (e.Item.ProjectObject is PXP.Crawler.API.Model.Program)
            {
                XtraTabPage progTabPage = FindTabPage(e.Item);
                if (progTabPage != null)
                {
                    progTabPage.Text = e.Item.Name;
                }
            }
        }

        protected override void Dispose(bool disposing)
        {
            explorerControl.Dispose();
            if (Program.mainForm.ActiveMdiChild == this)
            {
                Program.mainForm.emptyLabelControl.Visible = true;
                Program.mainForm.nodesTreePanel.Visible = false;
            }

            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #endregion

        #region Overrides

        public override bool CanSave
        {
            get { return true; }
        }

        public override void DoSave(string filePath)
        {
            OnBeforeSave();

            project.SaveToFile(filePath);
            base.DoSave(filePath);

            OnAfterSave();
        }

        #endregion

        #region Properties

        public bool PreferencesVisible
        {
            get { return projectXtraTabPage.Visible; }
            set { projectXtraTabPage.Visible = value; }
        }

        #endregion

        #region Methods

        private void OnBeforeSave()
        {
            foreach (XtraTabPage ptPage in pagesXtraTabControl.TabPages)
            {
                if (ptPage.Tag is ProjectItem)
                {
                    ProjectItem pi = (ProjectItem)ptPage.Tag;
                    if (pi.Type == ProjectItem.ProjectItemType.Program)
                    {
                        ProgramDesignerControl pdCont = (ProgramDesignerControl)ptPage.Controls[0];
                        pdCont.programNodesControl.oldScrollPos = pdCont.programNodesControl.AutoScrollPosition;
                        pdCont.programNodesControl.AutoScrollPosition = new Point(0, 0);
                        //pdCont.Invalidate(true);
                    }
                }
            }
        }

        private void OnAfterSave()
        {
            foreach (XtraTabPage ptPage in pagesXtraTabControl.TabPages)
            {
                if (ptPage.Tag is ProjectItem)
                {
                    ProjectItem pi = (ProjectItem)ptPage.Tag;
                    if (pi.Type == ProjectItem.ProjectItemType.Program)
                    {
                        ProgramDesignerControl pdCont = (ProgramDesignerControl)ptPage.Controls[0];
                        pdCont.programNodesControl.AutoScrollPosition = new Point(-pdCont.programNodesControl.oldScrollPos.X, -pdCont.programNodesControl.oldScrollPos.Y);
                        pdCont.Invalidate(true);
                    }
                }
            }
        }

        private XtraTabPage FindTabPage(ProjectItem pi)
        {
            foreach (XtraTabPage tp in pagesXtraTabControl.TabPages)
            {
                if (tp.Tag == pi)
                    return tp;
            }
            return null;
        }

        #endregion

        #region Internal Events

        private void project_LogMessage(object sender, ProjectLogMessageEventArgs e)
        {
            Program.mainForm.Log(e.Message, e.Type);
        }


        private void nameTextEdit_TextChanged(object sender, EventArgs e)
        {
            project.Name = nameTextEdit.Text;
            Text = nameTextEdit.Text;
        }


        private void ProjectXtraForm_Activated(object sender, EventArgs e)
        {
            explorerControl.Visible = true;
            Program.mainForm.emptyLabelControl.Visible = false;
            Program.mainForm.nodesTreePanel.Visible = true;
        }

        private void ProjectXtraForm_Deactivate(object sender, EventArgs e)
        {
            explorerControl.Visible = false;
            Program.mainForm.nodesTreePanel.Visible = false;
        }

        private void pagesXtraTabControl_MouseDown(object sender, MouseEventArgs e)
        {
            XtraTabHitInfo hInfo = pagesXtraTabControl.CalcHitInfo(e.Location);
            if (hInfo.HitTest == XtraTabHitTest.PageHeader)
            {
                if (e.Button == MouseButtons.Middle)
                {
                    if (hInfo.Page == projectXtraTabPage)
                    {
                        pagesXtraTabControl.TabPages.Remove(hInfo.Page);
                    }
                    else
                    {
                        pagesXtraTabControl.TabPages.Remove(hInfo.Page);
                        hInfo.Page.Dispose();
                    }
                }
            }
        }

        internal void projectDesignerControl_OpenItem(object sender, ProjectItemEventArgs e)
        {
            if (e.Item == project.RootProjectItem)
            {
                if (!pagesXtraTabControl.TabPages.Contains(projectXtraTabPage))
                    pagesXtraTabControl.TabPages.Add(projectXtraTabPage);
                pagesXtraTabControl.SelectedTabPage = projectXtraTabPage;
            }
            else
            {
                if (e.Item.Type != ProjectItem.ProjectItemType.Folder &&
                    e.Item.Type != ProjectItem.ProjectItemType.Other)
                {
                    XtraTabPage tabPage = FindTabPage(e.Item);
                    if (tabPage == null)
                    {
                        tabPage = new XtraTabPage();
                        tabPage.Text = e.Item.Name;
                        tabPage.Tag = e.Item;

                        if (e.Item.Type == ProjectItem.ProjectItemType.Program)
                        {
                            ProgramDesignerControl pdCont =
                                new ProgramDesignerControl((API.Model.Program) e.Item.ProjectObject);
                            pdCont.Dock = DockStyle.Fill;
                            tabPage.Controls.Add(pdCont);
                            tabPage.Image = imageCollection.Images["program"];
                            pdCont.SelectionChanged += pdCont_SelectionChanged;
                        }
                        else if (e.Item.Type == ProjectItem.ProjectItemType.Script)
                        {
                            CodeEditorControl ceCont = new CodeEditorControl(project, e.Item);
                            ceCont.Dock = DockStyle.Fill;
                            tabPage.Controls.Add(ceCont);
                            tabPage.Image = imageCollection.Images["script"];
                        }

                        pagesXtraTabControl.TabPages.Add(tabPage);
                    }
                    pagesXtraTabControl.SelectedTabPage = tabPage;
                }
            }
        }

        private struct PGEmptyStruct
        {
        }

        private void pdCont_SelectionChanged(object sender, EventArgs e)
        {
            ProgramDesignerControl pdCont = (ProgramDesignerControl) sender;
            Program.mainForm.nodePropertyGridControl.SelectedObjects = pdCont.SelectedNodes.ToArray();

            if (pdCont.SelectedNodes.Count == 0)
            {
                Program.mainForm.nodePropertyGridControl.Rows.Clear();
                /*Program.mainForm.nodePropertyGridControl.CloseEditor();
                Program.mainForm.nodePropertyGridControl.SelectedObjects = new object[] { new PGEmptyStruct() };
                Program.mainForm.nodePropertyGridControl.Update(); 
                Program.mainForm.nodePropertyGridControl.Refresh(); */
            }
        }

        private void projectDesignerControl_RemoveItem(object sender, ProjectItemEventArgs e)
        {
            XtraTabPage fTabPage = FindTabPage(e.Item);
            if (fTabPage != null)
            {
                pagesXtraTabControl.TabPages.Remove(fTabPage);
                fTabPage.Dispose();
            }
        }

        private void pagesXtraTabControl_SelectedPageChanged(object sender, TabPageChangedEventArgs e)
        {
            if (e.Page != null)
            {
                if (e.Page.Tag is ProjectItem)
                {
                    if (((ProjectItem) e.Page.Tag).Type == ProjectItem.ProjectItemType.Program)
                    {
                        Program.mainForm.nodePropertyGridControl.SelectedObjects =
                            ((ProgramDesignerControl) e.Page.Controls[0]).SelectedNodes.ToArray();
                    }
                }
            }
            else
            {
                Program.mainForm.nodePropertyGridControl.SelectedObject = null;
                Program.mainForm.nodePropertyGridControl.Refresh();
            }
        }

        private void ProjectXtraForm_Load(object sender, EventArgs e)
        {
            //projectDesignerControl.addProgramBarButtonItem.PerformClick();
            pagesXtraTabControl.TabPages.Remove(projectXtraTabPage);


        }

        private void ProjectXtraForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            OnBeforeSave();
            project.SaveToFile(Program.exePath + "current_project.pxcproj");
            project.Dispose();
        }

        #endregion

        private void projectDesignerControl_DoSelectItemInPropertyGrid(object sender, EventArgs e)
        {
            Program.mainForm.nodePropertyGridControl.SelectedObject = projectDesignerControl.SelectedItem;
        }

        private void projectDesignerControl_SelectionChanged(object sender, EventArgs e)
        {
            //Program.mainForm.nodePropertyGridControl.SelectedObject = projectDesignerControl.SelectedItem;
        }

        private void projectDesignerControl_CompileResult(object sender, ProjectCompilerResultEventArgs e)
        {
            Program.mainForm.errorsUserControl.ErrorsClear();
            
            foreach (XtraTabPage pTabPage in pagesXtraTabControl.TabPages)
            {
                ProjectItem tppi = (ProjectItem)pTabPage.Tag;
                if (tppi.Type == ProjectItem.ProjectItemType.Script)
                {
                    CodeEditorControl ceCont = (CodeEditorControl)pTabPage.Controls[0];
                    ceCont.ClearErrorLines();
                    break;
                }
            }

            if (e.CompilerResults.Errors.Count == 0)
            {
                if (Program.mainForm.outputDockPanel.Visible)
                {
                    Program.mainForm.outputDockPanel.Focus();
                    Program.mainForm.outputDockPanel.Select();
                    if (Program.mainForm.outputDockPanel.Parent != null)
                    {
                        DockPanel pdp = (DockPanel) Program.mainForm.outputDockPanel.Parent;
                        if (pdp.Tabbed)
                        {
                            pdp.ActiveChild = Program.mainForm.outputDockPanel;
                        }
                    }
                }
            }
            else
            {
                

                foreach (CompilerError ce in e.CompilerResults.Errors)
                {
                    int piInd = Conv.StringToInt(ce.FileName, 0);
                    ProjectItem pi = e.ProjectItems[piInd];
                    Program.mainForm.errorsUserControl.ErrorsAdd(pi, ce);



                    foreach (XtraTabPage pTabPage in pagesXtraTabControl.TabPages)
                    {
                        ProjectItem tppi = (ProjectItem)pTabPage.Tag;
                        if (tppi.Type == ProjectItem.ProjectItemType.Script)
                        {
                            if (tppi == pi)
                            {
                                CodeEditorControl ceCont = (CodeEditorControl)pTabPage.Controls[0];
                                ceCont.AddErrorLine(ce.Line - 1, ce.Column, ce.ErrorText);
                                break;
                            }
                        }
                    }
                }

                
                Program.mainForm.errorsDockPanel.Show();
                Program.mainForm.outputDockPanel.Focus();                
            }


        }


    }
}