using Microsoft.UI.Input;

using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.System;
using static Sonex.Client.Controls.DataGridView.DataGridView;

namespace Sonex.Client.Controls.DataGridView
{
    public sealed partial class DataGridView
    {
        CellVector? _ActiveCell;
        IntBitSet _SelectedRows;
        private PointerRoutedEventArgs lastPointerRoutedEventArgs;
        private PointerPoint? _LastPointer = null;
        private uint _pointerId;
        private bool _lastActionIsPointer = false;

        private SelectRange _SelectRange = new SelectRange();
        private void OnCellPressed(PointerRoutedEventArgs e)
        {
            PointerPoint? pointer = e.GetCurrentPoint(_Canvas);
            CellVector? Vector = GetCellByPointer(pointer);

            if (_ActiveCell == Vector) return;

            bool Shift = e.KeyModifiers.HasFlag(VirtualKeyModifiers.Shift);
            bool Alt = e.KeyModifiers.HasFlag(VirtualKeyModifiers.Menu);
            bool Ctrl = e.KeyModifiers.HasFlag(VirtualKeyModifiers.Control);


            if (MouseLeftButtonDown)
            {
                if (Ctrl && !Shift && !Alt)
                {
                    _SelectRange.From = Vector;
                    _SelectRange.To = Vector;
                    _SelectRange.Remove = false;
                }
                else if (!Ctrl && Shift && !Alt)
                {
                    _SelectRange.From = _ActiveCell;
                    _SelectRange.To = Vector;
                    _SelectRange.Remove = false;
                }
                else if (!Ctrl && !Shift && Alt)
                {
                    _SelectRange.From = Vector;
                    _SelectRange.To = Vector;
                    _SelectRange.Remove = true;
                    _SelectRange.RemoveOption = RemoveOption.Row;
                }
                else if (Ctrl && !Shift && Alt)
                {
                    _SelectRange.From = Vector;
                    _SelectRange.To = Vector;
                    _SelectRange.Remove = true;
                    _SelectRange.RemoveOption = RemoveOption.Column;
                }
                else if (Ctrl && Shift && !Alt)
                {
                    _SelectRange.Clear();
                    _SelectRange.Remove = false;

                }
                else
                {
                    UnSellectAll();
                    _SelectRange.From = Vector;
                    _SelectRange.To = Vector;
                    _SelectRange.Remove = false;
                }

                _ActiveCell = Vector;
            }


            RequestRender();
        }

        private void OnCellDrag(PointerRoutedEventArgs e)
        {

            if (e != null)
            {
                var p = e.GetCurrentPoint(_Canvas);
                if (p != null)
                {
                    _LastPointer = p;
                    _pointerId = p.PointerId;
                }
            }

            //e = lastPointerRoutedEventArgs;
            //if (e == null)
            //    return;
            //lastPointerRoutedEventArgs = e;
            //PointerPoint? pointer = e.GetCurrentPoint(_Canvas);
            CellVector? Vector = GetCellByPointer(_LastPointer);
            if(Vector == null) return;
            if (_LastPointer.Properties.IsLeftButtonPressed)
            {
                if (_SelectRange.From == null)
                {
                    _SelectRange.From = Vector;
                    _SelectRange.To = Vector;
                }
                else
                {
                    _SelectRange.To = Vector;
                }


                // Przewijanie krawędziowe w pionie
                if (_LastPointer.Position.Y > ActualHeight - 80)
                {
                    double power = Math.Clamp(((ActualHeight - _LastPointer.Position.Y) / 80d) * 400, 20, 400);
                    _ScrollMoverVertical.GoToEnd(power);
                }
                else if (_LastPointer.Position.Y < _HeaderHeight + _RowsHeight)
                {
                    double power = Math.Clamp(_LastPointer.Position.Y / (_HeaderHeight + _RowsHeight) * 400, 20, 400);
                    _ScrollMoverVertical.GoToStart(power);
                }
                else
                    _ScrollMoverVertical.Stop();

                // Przewijanie krawędziowe w poziomie

                if (_LastPointer.Position.X > ActualWidth - 80)
                {
                    double power = Math.Clamp((1d - ((ActualWidth - _LastPointer.Position.X) / 80d)) * 50d, 1d, 50d);
                    _ScrollMoverHorizontal.GoToEnd(step: power);
                }
                else if (_LastPointer.Position.X < _IndexColWidth + _PinedColWidth + 80 && _ActiveCell != null && !_ActiveCell.Header.IsPinned)
                {
                    //double power = Math.Clamp((1d - ((pointer.Position.X - (_IndexColWidth + _PinedColWidth)) / 80d)) * 25, 1, 25);
                    double power = (1d - (Math.Clamp(_LastPointer.Position.X - _IndexColWidth - _PinedColWidth, 0, 80) / 80d)) * 50d;
                    _ScrollMoverHorizontal.GoToStart(step: power);
                }
                else
                    _ScrollMoverHorizontal.Stop();
            }


            RequestRender();
        }
        private void OnCellDoubleTapped(PointerPoint e)
        {
            RequestRender();
        }
        private void _ApplySelectRange()
        {
            if (_SelectRange.From != null && _SelectRange.To != null && _ActiveCell != null)
            {
                int ColMin = Math.Min(_SelectRange.From.ColumnIndex, _SelectRange.To.ColumnIndex);
                int ColMax = Math.Max(_SelectRange.From.ColumnIndex, _SelectRange.To.ColumnIndex);
                int RowMin = Math.Min(_SelectRange.From.RowIndex, _SelectRange.To.RowIndex);
                int RowMax = Math.Max(_SelectRange.From.RowIndex, _SelectRange.To.RowIndex);


                if (_SelectRange.Remove)
                {
                    _ActiveCell = _SelectRange.To;
                    if (_SelectRange.RemoveOption == RemoveOption.Row)
                    {
                        _SelectedRows.RemoveRange(RowMin, RowMax);
                        var selectedRowsCount = _SelectedRows.Count();
                        if (selectedRowsCount == 0)
                            UnSellectAll();


                    }
                    else if (_SelectRange.RemoveOption == RemoveOption.Column)
                    {
                        _Columns
                        .Where(c => c.Index >= ColMin && c.Index <= ColMax)
                        .ToList()
                        .ForEach(c => c.isSelected = false);

                        var selectedColumnsCount = _Columns.Count(x => x.isSelected);
                        if (selectedColumnsCount == 0)
                            UnSellectAll();
                    }
                }
                else
                {
                    _Columns
                    .Where(c => c.Index >= ColMin && c.Index <= ColMax)
                    .ToList()
                    .ForEach(c => c.isSelected = true);
                    _SelectedRows.AddRange(RowMin, RowMax);
                    _ActiveCell = _SelectRange.To;
                }
                
            }
            _SelectRange.Clear();
            UpdateFooterTextSelected();
        }
 

        private void OnCellReleased(PointerRoutedEventArgs e)
        {
            _ScrollMoverVertical.Stop();
            _ScrollMoverHorizontal.Stop();

            //if (_lastActionIsPointer)
                _ApplySelectRange();
           
            RequestRender();
            _lastActionIsPointer = true;
        }
        private CellVector? GetCellByPointer(PointerPoint pointerPoint)
        {
            if (pointerPoint == null) return null;
            var pos = pointerPoint.Position;
            Column? columnHeader = GetColumnAtPosition(pos);
            var rowIndex = GetRowIndexAtPosition(pos);
            if (columnHeader != null && rowIndex < _ItemsSourceFiltred?.Count)
            {
                return new CellVector((Column)columnHeader, rowIndex);
            }
            return null;
        }

        private int GetRowIndexAtPosition(Point pos)
        {
            double Y = (pos.Y - _HeaderHeight);
            int index = (int)(Y / _RowsHeight);
            return Math.Min(index + _TopRowIndex, _ItemsSourceFiltred?.Count-1 ?? 0);
        }

        private Column? GetColumnAtPosition(Point pos)
        {
            foreach (var column in _Columns)
            {
                if (column.IsPinned && pos.X >= column.LeftOnScreen && pos.X < (column.LeftOnScreen + column.Width + 8))
                {
                    return column;
                }
            }

            foreach (Column column in _Columns)
            {
                if (pos.X >= column.LeftOnScreen && pos.X < (column.LeftOnScreen + column.Width + 8))
                {
                    return column;
                }
            }

            if (pos.X < _IndexColWidth) return _Columns.First();
            if (pos.X > ActualWidth) return _Columns.Last();
            return null;
        }

        public void UnSellectAll()
        {
            _SelectRange.Clear();
            _SelectedRows.Clear();
            foreach(var column in _Columns)
            {
                column.isSelected = false;
            }
        }

        public void SellectAll()
        {
            _SelectRange.Clear();
            _SelectedRows.SelectAll();
            foreach (var column in _Columns)
            {
                column.isSelected = true;
            }
        }

    }
}
