//------------------------------------------------------------------------------
// <copyright file=”*.cs” company=”EhLib Team”>
//     Copyright (c) 2017 Dmitry V. Bolshakov   
// </copyright>
//------------------------------------------------------------------------------

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

namespace EhLib
{
  public partial class BaseCustomizePropBarsDialog : Form
  {
    
    [Obfuscation(Feature = "renaming", Exclude = true, ApplyToMembers = false)] 
    public class AxisGridPropDataRow
    {
      public PropertyAxisBar PropBar { get; set; }
      public bool VisibleState { get; set; }
      public string Name { get; set; }
    }

    private List<AxisGridPropDataRow> propsTable;// = new List<AxisGridPropDataRow>();
    private List<AxisGridPropDataRow> dataViewVisibleProps;// = new List<AxisGridPropDataRow>();
    private List<AxisGridPropDataRow> dataViewHidenProps;// = new List<AxisGridPropDataRow>();

    //private DataTable propsTable;
    //private DataView dataViewVisibleProps = new DataView();
    //private DataView dataViewHidenProps = new DataView();
    private DataAxisGrid dataGrid;

    //protected int refColumnColIndex;
    //protected int visibleStateColIndex;
    //protected int nameColIndex;

    public BaseCustomizePropBarsDialog()
    {
      InitializeComponent();

      propsTable = CreateTable();
      dataViewVisibleProps = CreateDataViewVisiblePropsList();
      dataViewHidenProps = CreateDataViewHidenPropsList();
    }

    public DataAxisGrid DataGrid { get { return dataGrid; } }
    public DataGridEh HidenPropBarsGrid { get { return hidenPropBarsGrid; } }
    public DataGridEh VisiblePropBarsGrid { get { return visiblePropBarsGrid; } }
    public DataGridTextColumn VisGridNameColumn { get { return visGridNameColumn; } }
    public DataGridTextColumn HidGridNameColumn { get { return hidGridNameColumn; } }
    public List<AxisGridPropDataRow> PropsTable { get { return propsTable; } }
    public List<AxisGridPropDataRow> DataViewVisibleProps { get { return dataViewVisibleProps; } }
    public List<AxisGridPropDataRow> DataViewHidenProps { get { return dataViewHidenProps; } }

    //public DataView DataViewVisibleProps { get { return dataViewVisibleProps; } }
    //public DataView DataViewHidenProps { get { return dataViewHidenProps; } }

    //public DataTable PropsTable { get { return propsTable; } }

    public static bool ShowCustomizePropBarsDialog(DataAxisGrid grid)
    {
      BaseCustomizePropBarsDialog dialog = new BaseCustomizePropBarsDialog();
      return dialog.ShowDialog(grid);
    }

    protected virtual List<AxisGridPropDataRow> CreateTable()
    {
      return new List<AxisGridPropDataRow>();
    }

    protected virtual List<AxisGridPropDataRow> CreateDataViewVisiblePropsList()
    {
      return new List<AxisGridPropDataRow>();
    }

    protected virtual List<AxisGridPropDataRow> CreateDataViewHidenPropsList()
    {
      return new List<AxisGridPropDataRow>();
    }

    public new virtual bool ShowDialog(DataAxisGrid grid)
    {
      dataGrid = grid;
      InitData();

      if (ShowDialog() == DialogResult.OK)
      {
        WriteGridBarsData();
        return true;
      }
      else
      {
        return false;
      }
    }

    protected virtual void WriteGridBarsData()
    {
      DataGrid.PropBars.BeginUpdate();
      try
      {
        int i = 0;
        foreach (AxisGridPropDataRow propBarDataRow in propsTable)
        {
          PropertyAxisBar propBar = propBarDataRow.PropBar;
          WritePropBarFromPropBarDataRow(propBar, propBarDataRow, i);
          i++;
        }
      }
      finally
      {
        DataGrid.PropBars.EndUpdate();
      }
    }

    protected virtual void WritePropBarFromPropBarDataRow(PropertyAxisBar propBar, AxisGridPropDataRow propBarDataRow, int index)
    {
      propBar.Visible = propBarDataRow.VisibleState;
      propBar.DisplayIndex = index;
    }

    protected virtual void InitData()
    {
      ReadPropBars();

      //dataViewVisibleProps.Table = propsTable;
      //dataViewVisibleProps.RowFilter = "VisibleState = true";
      //visiblePropBarsGrid.DataSource = dataViewVisibleProps;
      bsVisiblePropBars.DataSource = dataViewVisibleProps;

      //dataViewHidenProps.Table = propsTable;
      //dataViewHidenProps.RowFilter = "VisibleState <> true";
      //hidenPropBarsGrid.DataSource = dataViewHidenProps;
      bsHidenPropBars.DataSource = dataViewHidenProps;

      bSetWidth.Visible = false;
    }

    protected virtual void ReadPropBars()
    {
      foreach (PropertyAxisBar propBar in DataGrid.ViewOrderedPropBars)
      {
        AxisGridPropDataRow dataTow = CreateNewPropsDataRow(propBar);
        InitNewPropDataRow(dataTow, propBar);
        propsTable.Add(dataTow);
      }
      RefreshScreenLists();
    }

    protected virtual AxisGridPropDataRow CreateNewPropsDataRow(PropertyAxisBar propBar)
    {
      return new AxisGridPropDataRow();
    }

    protected virtual void InitNewPropDataRow(AxisGridPropDataRow dataRow, PropertyAxisBar propBar)
    {
      dataRow.PropBar = propBar;
      dataRow.VisibleState = propBar.Visible;
      dataRow.Name = propBar.Title.Text;
    }

    private void bHideSelected_Click(object sender, EventArgs e)
    {
      HideSelectedPropBars();
    }

    private void bShowSelected_Click(object sender, EventArgs e)
    {
      ShowSelectedPropBars();
    }

    private void visGridNameColumn_DataCellMouseDoubleClick(object sender, DataGridDataCellMouseEventArgs e)
    {
      HideSelectedPropBars();
    }

    private void hidGridNameColumn_DataCellMouseDoubleClick(object sender, DataGridDataCellMouseEventArgs e)
    {
      ShowSelectedPropBars();
    }

    private void bMoveUp_Click(object sender, EventArgs e)
    {
      MovePropBarsUpDown(true);
    }

    private void bMoveDown_Click(object sender, EventArgs e)
    {
      MovePropBarsUpDown(false);
    }

    protected virtual void MovePropBarsUpDown(bool isMoveUp)
    {
      if (visiblePropBarsGrid.VisibleRows.Count == 0) return;

      List<AxisGridPropDataRow> listForHide = new List<AxisGridPropDataRow>();
      List<AxisGridPropDataRow> newRowList = new List<AxisGridPropDataRow>();
      List<PropertyAxisBar> movedPropBars = new List<PropertyAxisBar>();
      int firstSelGridIndex = -1;
      int lastSelGridIndex = -1;
      int moveToDataRowIndex = -1;
      AxisGridPropDataRow firstSel = null;
      AxisGridPropDataRow baseDataRow = null;

      foreach (DataGridRow row in visiblePropBarsGrid.VisibleRows)
      {
        if (row.Selected)
        {
          listForHide.Add(row.SourceItem as AxisGridPropDataRow);
          if (firstSelGridIndex == -1)
          {
            firstSelGridIndex = row.VisibleIndex;
            firstSel = row.SourceItem as AxisGridPropDataRow;
          }
          lastSelGridIndex = row.VisibleIndex;
        }
      }

      if (listForHide.Count == 0)
      {
        DataGridRow gridRow = visiblePropBarsGrid.CurrentRow;
        firstSel = gridRow.SourceItem as AxisGridPropDataRow;
        listForHide.Add(firstSel);
        firstSelGridIndex = gridRow.VisibleIndex;
        lastSelGridIndex = gridRow.VisibleIndex;
        
      }

      foreach (AxisGridPropDataRow rowView in listForHide)
      {
        propsTable.Remove(rowView);
      }

      if (isMoveUp)
      {
        if (firstSelGridIndex > 0) firstSelGridIndex = firstSelGridIndex - 1;
        baseDataRow = visiblePropBarsGrid.VisibleRows[firstSelGridIndex].SourceItem as AxisGridPropDataRow;
      }
      else
      {
        if (lastSelGridIndex < visiblePropBarsGrid.VisibleRows.Count-1) lastSelGridIndex = lastSelGridIndex + 1;
        baseDataRow = visiblePropBarsGrid.VisibleRows[lastSelGridIndex].SourceItem as AxisGridPropDataRow;
      }

      moveToDataRowIndex = propsTable.IndexOf(baseDataRow);

      if (isMoveUp)
      {
        if (moveToDataRowIndex == -1) moveToDataRowIndex = 0;
      }
      else
      {
        if (moveToDataRowIndex == -1 || moveToDataRowIndex == propsTable.Count-1)
          moveToDataRowIndex = propsTable.Count;
        else
          moveToDataRowIndex = moveToDataRowIndex + 1;
      }

      listForHide.Reverse();

      foreach (AxisGridPropDataRow row in listForHide)
      {
        propsTable.Insert(moveToDataRowIndex, row);
        movedPropBars.Add(row.PropBar);
      }

      RefreshScreenLists();

      int i = 0;
      foreach (DataGridRow row in visiblePropBarsGrid.VisibleRows)
      {
        if ((row.SourceItem as AxisGridPropDataRow) == firstSel)
        {
          visiblePropBarsGrid.CurrentRowIndex = i;
          break;
        }
        i++;
      }

      foreach (DataGridRow row in visiblePropBarsGrid.VisibleRows)
      {
        AxisGridPropDataRow dataRow = (row.SourceItem as AxisGridPropDataRow);
        PropertyAxisBar propBar = dataRow.PropBar;
        if (movedPropBars.IndexOf(propBar) >= 0)
          row.Selected = true;
      }

    }

    protected virtual void HideSelectedPropBars()
    {
      List<AxisGridPropDataRow> listForHide = new List<AxisGridPropDataRow>();

      foreach (DataGridRow row in visiblePropBarsGrid.Rows)
      {
        if (row.Selected)
          listForHide.Add(row.SourceItem as AxisGridPropDataRow);
      }

      if (listForHide.Count == 0 && visiblePropBarsGrid.VisibleRows.Count > 0)
        listForHide.Add(visiblePropBarsGrid.CurrentRow.SourceItem as AxisGridPropDataRow);

      foreach (AxisGridPropDataRow rowView in listForHide)
      {
        rowView.VisibleState = false;
      }

      RefreshScreenLists();
    }

    protected virtual void ShowSelectedPropBars()
    {
      List<AxisGridPropDataRow> listForShow = new List<AxisGridPropDataRow>();

      foreach (DataGridRow row in hidenPropBarsGrid.Rows)
      {
        if (row.Selected)
          listForShow.Add(row.SourceItem as AxisGridPropDataRow);
      }

      if (listForShow.Count == 0 && hidenPropBarsGrid.VisibleRows.Count > 0)
        listForShow.Add(hidenPropBarsGrid.CurrentRow.SourceItem as AxisGridPropDataRow);

      foreach (AxisGridPropDataRow rowView in listForShow)
      {
        rowView.VisibleState = true;
      }

      RefreshScreenLists();
    }

    protected virtual void bSetWidth_Click(object sender, EventArgs e)
    {
    }

    protected virtual void RefreshScreenLists()
    {
      RefreshDataViewVisibleProps();
      RefreshDataViewHidenProps();
    }

    protected virtual void RefreshDataViewVisibleProps()
    {
      dataViewVisibleProps.Clear();

      foreach (AxisGridPropDataRow propBarDataRow in propsTable)
      {
        if (IsPropRowInVisibleList(propBarDataRow))
          dataViewVisibleProps.Add(propBarDataRow);
      }

      int oldPos = bsVisiblePropBars.Position;
      bsVisiblePropBars.ResetBindings(false);
      bsVisiblePropBars.Position = Math.Min(oldPos, bsVisiblePropBars.Count - 1);
    }

    protected virtual bool IsPropRowInVisibleList(AxisGridPropDataRow propBarDataRow)
    {
      return propBarDataRow.VisibleState;
    }

    protected virtual void RefreshDataViewHidenProps()
    {
      DataViewHidenProps.Clear();

      foreach (AxisGridPropDataRow propBarDataRow in propsTable)
      {
        if (IsPropRowInHidenList(propBarDataRow))
          DataViewHidenProps.Add(propBarDataRow);
      }

      int oldPos = bsHidenPropBars.Position;
      bsHidenPropBars.ResetBindings(false);
      bsHidenPropBars.Position = Math.Min(oldPos, bsHidenPropBars.Count-1);
    }

    protected virtual bool IsPropRowInHidenList(AxisGridPropDataRow propBarDataRow)
    {
      return !propBarDataRow.VisibleState;
    }

  }

  public class DynaTypedList<T> : List<T>, ITypedList
  {
    private Type itemType;

    public DynaTypedList(Type itemType)
    {
      this.itemType = itemType;
    }

    PropertyDescriptorCollection ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors)
    {
      if (listAccessors == null)
        return TypeDescriptor.GetProperties(itemType);
      else
        return null;
    }

    string ITypedList.GetListName(PropertyDescriptor[] listAccessors)
    {
      return "";
    }
  }
}
