using System;
using System.ComponentModel;
using System.Windows.Forms;
using FastReport.Controls;
using FastReport.Design.PageDesigners.Page;
using FastReport.Table;
using FastReport.Utils;

namespace FastReport.AdvMatrix
{

    public partial class AdvMatrixObject
    {
        #region Fields
        private bool descriptorsUpdated;
        #endregion

        #region Properties
        /// <summary>
        /// This property is not relevant to this class.
        /// </summary>
        [Browsable(false)]
        public override int ColumnCount
        {
            get { return base.ColumnCount; }
            set { base.ColumnCount = value; }
        }

        /// <summary>
        /// This property is not relevant to this class.
        /// </summary>
        [Browsable(false)]
        public override int RowCount
        {
            get { return base.RowCount; }
            set { base.RowCount = value; }
        }

        /// <summary>
        /// This property is not relevant to this class.
        /// </summary>
        [Browsable(false)]
        public new int FixedRows
        {
            get { return base.FixedRows; }
            set { base.FixedRows = value; }
        }

        /// <summary>
        /// This property is not relevant to this class.
        /// </summary>
        [Browsable(false)]
        public new int FixedColumns
        {
            get { return base.FixedColumns; }
            set { base.FixedColumns = value; }
        }

        /// <summary>
        /// This property is not relevant to this class.
        /// </summary>
        [Browsable(false)]
        public new bool CanBreak
        {
            get { return base.CanBreak; }
            set { base.CanBreak = value; }
        }

        /// <summary>
        /// This property is not relevant to this class.
        /// </summary>
        [Browsable(false)]
        public new bool GrowToBottom
        {
            get { return base.GrowToBottom; }
            set { base.GrowToBottom = value; }
        }

        /// <summary>
        /// This property is not relevant to this class.
        /// </summary>
        [Browsable(false)]
        public new string EvenStyle
        {
            get { return base.EvenStyle; }
            set { base.EvenStyle = value; }
        }
        #endregion

        #region Public Methods
        internal void UpdateDescriptors(bool forceUpdate = false)
        {
            if (forceUpdate || !descriptorsUpdated)
            {
                TemplateBuilder.UpdateDescriptors(this);
                descriptorsUpdated = true;
            }
        }

        internal void SwapColumnsRows()
        {
            AdvMatrixObject matrix = new AdvMatrixObject();
            matrix.AssignAll(this, true);

            Clear();
            ColumnCount = matrix.RowCount;
            RowCount = matrix.ColumnCount;
            
            for (int x = 0; x < ColumnCount; x++)
            {
                Columns[x].CreateUniqueName();
            }

            for (int y = 0; y < RowCount; y++)
            {
                Rows[y].CreateUniqueName();
            }

            for (int x = 0; x < matrix.ColumnCount; x++)
            {
                for (int y = 0; y < matrix.RowCount; y++)
                {
                    this[y, x].AssignAll(matrix[x, y], true);
                    this[y, x].ColSpan = matrix[x, y].RowSpan;
                    this[y, x].RowSpan = matrix[x, y].ColSpan;
                }
            }

            Data.Columns.Assign(matrix.Data.Rows);
            Data.Rows.Assign(matrix.Data.Columns);
            matrix.Dispose();

            UpdateDescriptors(true);
            BuildTemplate();
            FixParentHeight();
        }

        /// <inheritdoc/>
        public override void OnBeforeInsert(int flags)
        {
            BuildTemplate();

            float width;
            if (Page is ReportPage && (Page as ReportPage).IsImperialUnitsUsed)
                width = Units.Inches * 1;
            else
                width = Units.Centimeters * 2.5f;

            Columns[0].Width = width;
            Columns[1].Width = Columns[0].Width;
        }

        // fix matrix parent height on matrix change
        internal void FixParentHeight()
        {
            if (!IsDesigning)
                return;

            // get the matrix height. Height property may not be updated yet.
            float height = 0;
            foreach (TableRow row in Rows)
                height += row.Height;
            
            if (Top + height > (Parent as ComponentBase).Height)
            {
                (Parent as ComponentBase).Height = Top + height;
                (Report.Designer.ActiveReportTab.ActivePageDesigner as Design.PageDesigners.Page.ReportPageDesigner).Workspace.UpdateBands();
            }
        }

        /// <inheritdoc/>
        public override ContextMenuBase GetContextMenu()
        {
            return new MatrixObjectMenu(Report.Designer);
        }

        internal override ContextMenuBase GetCellContextMenu(TableCell cell)
        {
            switch (cell.GetMatrixElement())
            {
                case MatrixElement.Corner:
                    return new MatrixCellMenuBase(this);
                case MatrixElement.Cell:
                    return new MatrixCellMenu(this);
                case MatrixElement.Column:
                case MatrixElement.Row:
                    return new MatrixHeaderMenu(this);
            }
            return new MatrixCellMenuBase(this);
        }

        internal override SmartTagBase GetCellSmartTag(TableCell cell)
        {
            return new MatrixCellSmartTag(this, cell);
        }

        internal override void HandleCellDoubleClick(TableCell cell)
        {
            if (cell == null)
                return;
            MatrixElement el = cell.GetMatrixElement();

            if (el == MatrixElement.Column || el == MatrixElement.Row)
            {
                HeaderDescriptor descr = cell.GetHeaderDescriptor();
                if (descr != null)
                {
                    using (MatrixHeaderEditorForm form = new MatrixHeaderEditorForm(descr))
                    {
                        if (form.ShowDialog() == DialogResult.OK)
                        {
                            BuildTemplate();
                            FixParentHeight();
                            Report.Designer.SetModified(cell, "Change");
                        }
                    }
                }
                else
                {
                    // probably bad-formed template. Rebuild it
                    BuildTemplate();
                    FixParentHeight();
                    Report.Designer.SetModified(cell, "Change");
                }
            }
            else
            {
                if (cell.HasFlag(Flags.CanEdit) && !cell.HasRestriction(Restrictions.DontEdit) && cell.InvokeEditor())
                    Report.Designer.SetModified(cell, "Change");
            }
        }

        /// <inheritdoc/>
        public override void HandleKeyDown(Control sender, KeyEventArgs e)
        {
            bool myKey = false;
            TableCell cell = Report.Designer.SelectedObjects[0] as TableCell;
            if (!IsSelected || cell == null)
                return;

            switch (e.KeyCode)
            {
                case Keys.Delete:
                    bool deleted = false;
                    foreach (Base c in Report.Designer.SelectedObjects)
                    {
                        cell = c as TableCell;
                        if (cell != null)
                        {
                            MatrixElement element = cell.GetMatrixElement();
                            if (element == MatrixElement.Column || element == MatrixElement.Row)
                            {
                                HeaderDescriptor descr = cell.GetHeaderDescriptor();
                                if (descr != null && !descr.IsTopNItem)
                                {
                                    descr.DeleteTopNItems();
                                    descr.DeleteThis();
                                    deleted = true;
                                }
                            }
                            else
                            {
                                cell.Text = "";
                                deleted = true;
                            }
                        }
                    }
                    if (deleted)
                    {
                        if (!Report.Designer.IsPreviewPageDesigner)
                        {
                            BuildTemplate();
                            Report.Designer.ActiveReportTab.ActivePageDesigner.FillObjects(false);
                            Report.Designer.SelectedObjects.Clear();
                            Report.Designer.SelectedObjects.Add(this);
                            Report.Designer.SelectionChanged(null);
                        }
                        Report.Designer.SetModified(this, "Change");
                    }
                    myKey = true;
                    break;

                case Keys.Enter:
                    HandleCellDoubleClick(cell);
                    myKey = true;
                    break;
            }

            if (myKey)
                e.Handled = true;
            else
                base.HandleKeyDown(sender, e);
        }

        internal override string GetCellDisplayText(TableCell cell, string defaultText)
        {
            return cell.GetDisplayText(defaultText);
        }

        internal override void ProvideCustomItems(TableCell cell, DataTreeView tree)
        {
            cell.ProvideMatrixItems(tree);
        }
        #endregion

    }
}