using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Brushes;
using Microsoft.Graphics.Canvas.Effects;
using Microsoft.Graphics.Canvas.Text;
using Microsoft.Graphics.Canvas.UI.Xaml;
using Microsoft.UI.Text;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Media.Imaging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Numerics;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.UI;
using WinRT;
using static Npgsql.Replication.PgOutput.Messages.RelationMessage;

namespace Sonex.Client.Controls.DataGridView;

public sealed partial class DataGridView
{

    internal void RequestRender()
    {
        GenerateHeaders();

        CalcHeaders();
        CalcHorizontalScroll();
        CalcVerticalScroll();

        _Canvas?.Invalidate();
    }


    private CanvasTextFormat HeaderTextFormat = new CanvasTextFormat()
    {
        FontSize = 14f,
        FontFamily = "Calibri",
        FontWeight = FontWeights.Normal,
        
        HorizontalAlignment = CanvasHorizontalAlignment.Left,
        VerticalAlignment = CanvasVerticalAlignment.Bottom,
        WordWrapping = CanvasWordWrapping.NoWrap,
        TrimmingGranularity = CanvasTextTrimmingGranularity.Character,
        TrimmingSign = CanvasTrimmingSign.Ellipsis,

        //Direction = CanvasTextDirection.LeftToRightThenBottomToTop,
    };
    private CanvasTextFormat IconTextFormat = new CanvasTextFormat()
    {
        FontSize = 12f,
        FontFamily = "Segoe Fluent Icons",
        FontWeight = FontWeights.Normal,

        HorizontalAlignment = CanvasHorizontalAlignment.Center,
        VerticalAlignment = CanvasVerticalAlignment.Center,
        WordWrapping = CanvasWordWrapping.NoWrap,
        TrimmingGranularity = CanvasTextTrimmingGranularity.Character,
        TrimmingSign = CanvasTrimmingSign.Ellipsis,
        

        //Direction = CanvasTextDirection.LeftToRightThenBottomToTop,
    };

    private CanvasTextFormat IndexTextFormat = new CanvasTextFormat()
    {
        FontSize = 14f,
        FontFamily = "Calibri",
        FontWeight = FontWeights.Normal,

        HorizontalAlignment = CanvasHorizontalAlignment.Center,
        VerticalAlignment = CanvasVerticalAlignment.Center,
        WordWrapping = CanvasWordWrapping.NoWrap,
        TrimmingGranularity = CanvasTextTrimmingGranularity.Character,
        TrimmingSign = CanvasTrimmingSign.Ellipsis,

        //Direction = CanvasTextDirection.LeftToRightThenBottomToTop,
    };
    private readonly Stopwatch _drawWatch = new();

    //private void DrawActiveLine(CanvasDrawingSession ds)
    //{
    //    if (_ActiveCell != null &&
    //        _ActiveCell.RowIndex >= _TopRowIndex &&
    //        _ActiveCell.RowIndex < _TopRowIndex + _MaxIndexOnScreen
    //        )
    //    {

    //        float y = (float)Math.Round((_ActiveCell.RowIndex - _TopRowIndex) * _rowsHeightF + _headerHeightF);
    //        float w = (float)Math.Round(ActualWidth);
    //        float h = (float)Math.Round(_rowsHeightF);

    //        ds.FillRectangle(0, y, w, h, ActiveRowFillColor.Color);
    //    }
    //}

    private void DrawHeaders(CanvasDrawingSession ds)
    {
        for(int i = _Columns.Count-1; i >= 0; i--)
        {
            var column = _Columns[i];
            if (!column.IsOnScreen)
                continue;
            ds.Transform = Matrix3x2.CreateTranslation((float)(column.LeftOnScreen), 0);
            OnDrawHeader(ds, column);
        }
        ds.Transform = Matrix3x2.Identity;

    }

    public void OnDrawHeader(CanvasDrawingSession ds, Column column)
    {
        if (column.isSelected || _SelectRange.IsInclude(column))
        {
            ds.FillRectangle(0, 0, (float)column.Width, _HeaderHeight, HeaderBackColor.Color);
            ds.FillRectangle(0, 0, (float)column.Width, _HeaderHeight, ActiveRowFillColor.Color);
            ds.DrawLine(0, _HeaderHeight - 1.0f, (float)(column.Width), _HeaderHeight - 1.0f, ActiveCellborderColor.Color, 2f);
        }
        else
        {
            ds.FillRectangle(0, 0, (float)column.Width, _HeaderHeight, HeaderBackColor.Color);
        }
        if (HeaderHover != null && HeaderHover.Title == column.Title)
        {
            ds.DrawText(column.Title, 6f, 6f, (float)column.Width - 28f, _HeaderHeight - 12f, indexTextColor.Color, HeaderTextFormat);
            //ds.DrawLine((float)(column.Width - _headerHeightF) - 0.5f, 0f, (float)(column.Width - _headerHeightF) - 0.5f, _headerHeightF, borderColor.Color, 0.5f);
            //ds.FillRectangle((float)column.Width - _headerHeightF, 0f, _headerHeightF, _headerHeightF, SelectedCallFillColor);
            
            if (isHeaderStparatorHover)
                ds.DrawLine((float)(column.Width), 1.5f, (float)(column.Width), _HeaderHeight-3f, ActiveCellborderColor.Color, 3f);

            //Filter
            if (isHeaderFilterHover)
                ds.DrawText("\uE71C", 4f, 4f, 20f, 20f, HoverHeaderIconColor, IconTextFormat);
            else
                ds.DrawText("\uE71C", 4f, 4f, 20f, 20f, HeaderIconColor, IconTextFormat);

            // Sort
            if (isHeaderSortHover)
                ds.DrawText("\uE8CB", 24f, 4f, 20f, 20f, HoverHeaderIconColor, IconTextFormat);
            else
                ds.DrawText("\uE8CB", 24f, 4f, 20f, 20f, HeaderIconColor, IconTextFormat);


            //Hide col
            if (isHeaderColHideHover)
                ds.DrawText("\uED1A", (float)(column.Width - 44), 4f, 20f, 20f, HoverHeaderIconColor, IconTextFormat);
            else
                ds.DrawText("\uED1A", (float)(column.Width - 44), 4f, 20f, 20f, HeaderIconColor, IconTextFormat);

            // Pin
            if (isHeaderPinHover)
                ds.DrawText(column.IsPinned ? "\uE77A" : "\uE718", (float)(column.Width - 24), 4f, 20f, 20f, HoverHeaderIconColor, IconTextFormat);
            else
                ds.DrawText(column.IsPinned ? "\uE77A" : "\uE718", (float)(column.Width - 24), 4f, 20f, 20f, HeaderIconColor, IconTextFormat);

        }
        else
        {
            ds.DrawText(column.Title, 6f, 6f, (float)column.Width - 12f, _HeaderHeight - 12f, indexTextColor.Color, HeaderTextFormat);
        }


    }

    private void DrawVerticleLines(CanvasDrawingSession ds)
    {
        for (int i = _Columns.Count - 1; i >= 0; i--)
        {
            var column = _Columns[i];
            if (!column.IsOnScreen)
                continue;
            ds.DrawLine((float)(column.LeftOnScreen + column.Width - 0.5f), 0f, (float)(column.LeftOnScreen + column.Width - 0.5f), (float)_Canvas.ActualHeight, borderColor.Color, 0.5f);
        }
    }

    private void DrawHorizontalLines(CanvasDrawingSession ds)
    {
        int j = (int)_ScrollVertical.Value + 1;
        //double maxH = Math.Min(_Canvas.ActualHeight, _headerHeightF + ((_items?.Count ?? 0) * _rowsHeightF));

        for (float y = _HeaderHeight; y <= _Canvas.ActualHeight; y += _RowsHeight)
        {
            ds.DrawLine(0f, y - 0.5f, (float)_Canvas.ActualWidth, y - 0.5f, borderColor.Color, 0.5f);
        }


    }


    private void DrawIndex(CanvasDrawingSession ds)
    {
        ds.FillRectangle(0f, 0f, (float)_IndexColWidth, (float)_Canvas.ActualHeight, HeaderBackColor.Color);

        int j = (int)_ScrollVertical.Value + 1;
        for (float y = _HeaderHeight; y <= _Canvas.ActualHeight; y += _RowsHeight)
        {
            if ((_SelectedRows!=null && _SelectedRows[j - 1]) || _SelectRange.IsInclude(j - 1))
            {
                ds.FillRectangle(0f, y, (float)_IndexColWidth, _RowsHeight, ActiveRowFillColor.Color);
                ds.DrawLine((float)_IndexColWidth, y, (float)_IndexColWidth, y + _RowsHeight, ActiveCellborderColor.Color, 2f);
                ds.DrawText((j++).ToString(), 0f, y + 0.5f, (float)_IndexColWidth, _RowsHeight, selectedIndexTextColor, IndexTextFormat);

            }
            else
            {
                ds.DrawText((j++).ToString(), 0f, y + 0.5f, (float)_IndexColWidth, _RowsHeight, indexTextColor.Color, IndexTextFormat);

            }
            //if (j <= (_items?.Count ?? 0))

        }
        // Linia Indexu
        ds.DrawLine((float)(_IndexColWidth) + 0.5f, 0, (float)(_IndexColWidth) + 0.5f, (float)_Canvas.ActualHeight, borderColor.Color, 0.5f);
        ds.DrawLine((float)(_IndexColWidth + _PinedColWidth) + 0.5f, 0, (float)(_IndexColWidth + _PinedColWidth) + 0.5f, (float)_Canvas.ActualHeight, borderColor.Color, 0.5f);
        // Linia Nagłówków
        ds.DrawLine(0f, _HeaderHeight - 0.5f, (float)_Canvas.ActualWidth, _HeaderHeight - 0.5f, borderColor.Color, 0.5f);
        ds.DrawLine(0f, _HeaderHeight - 0.5f, (float)_Canvas.ActualWidth, _HeaderHeight - 0.5f, ActiveCellborderColor.Color, 0.5f);

        //ds.DrawLine(0f, (float)_Canvas.ActualHeight - 0.5f, (float)_Canvas.ActualWidth, (float)_Canvas.ActualHeight - 0.5f, borderColor.Color, 1f);
        //ds.DrawLine((float)_Canvas.ActualWidth, 0f, (float)_Canvas.ActualWidth, (float)_Canvas.ActualHeight - 0.5f, borderColor.Color, 1f);

    }

    private void DrawNoData(CanvasDrawingSession ds)
    {
        if (_ItemsSourceFiltred != null && _ItemsSourceFiltred.Count > 0) return;
        var rect = new Rect((_Canvas.ActualWidth * 0.5d - 150d), (_Canvas.ActualHeight * 0.5d - 40d), 300d, 80d);
        ds.FillRectangle(rect, backColor.Color);
        ds.DrawRectangle(rect, ActiveCellborderColor.Color,0.5f);
        ds.DrawText("No data available to display", rect, indexTextColor.Color, TextFormatCenter);

    }

    private async Task DrawLoadingBackGroundAsync(CanvasDrawingSession ds)
    {
        if (IsEnabled) return;
        var rect = new Rect(0,0, _Canvas.ActualWidth, _Canvas.ActualHeight);

        ds.FillRectangle(rect, LoadingBackColor);
        //ds.DrawRectangle(rect, ActiveCellborderColor.Color, 0.5f);
        //ds.DrawText("No data available to display", rect, indexTextColor.Color, TextFormatCenter);

    }
    private void Canvas_Draw(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args)
    {
        _drawWatch.Restart();

        Microsoft.Graphics.Canvas.CanvasDrawingSession ds = args.DrawingSession;
        ds.Clear(backColor.Color);
        //DrawHeaders(ds);
        if(_itemType != null)
        {
            for (int x = _Columns.Count - 1; x >= 0; x--)
            {
                var column = _Columns[x];
                if (column.IsOnScreen)
                {
                    ds.Transform = Matrix3x2.CreateTranslation((float)(column.LeftOnScreen), 0);
                    OnDrawHeader(ds, column);
                }
            }
        }

        if (_ItemsSourceFiltred != null && _ItemsSourceFiltred.Count > 0)
        {
            for (int x = _Columns.Count - 1; x >= 0; x--)
            {
                var column = _Columns[x];
                if (column.IsOnScreen)
                {
                    for (int i = 0; i < _MaxIndexOnScreen; i++)
                    {
                        int rowIndex = i + _TopRowIndex;
                        ds.Transform = Matrix3x2.CreateTranslation((float)(column.LeftOnScreen), _HeaderHeight + (i * _RowsHeight));
                        column.OnDrawCell(ds, rowIndex);
                    }
                }
            }
        }

        ds.Transform = Matrix3x2.Identity;
        DrawIndex(ds);
        DrawVerticleLines(ds);
        DrawHorizontalLines(ds);
        DrawNoData(ds);
        DrawLoadingBackGroundAsync(ds);


        _drawWatch.Stop();
        var fps = $"{(1000/_drawWatch.Elapsed.TotalMilliseconds):0}";
        ds.DrawText(fps, 0, 0, (float)_IndexColWidth, _HeaderHeight, indexTextColor.Color, TextFormatCenter);
    }


}
