private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            DpiScaler.Initialize(this);

            Width           = this.Width / DpiScaler.Scale.Value;
            Height          = this.Height / DpiScaler.Scale.Value;
            MainGrid.Margin = new(MainGrid.Margin.Left / DpiScaler.Scale.Value);

            Restart();
            TryLoadFromSave();
            ResetSettings();

            MapView.PaintSurface += this.MainView_PaintSurface;

            Showcase1View.MouseDown    += this.ShowcaseView_MouseDown;
            Showcase1View.PaintSurface += this.ShowcaseView_PaintSurface;
            Showcase2View.MouseDown    += this.ShowcaseView_MouseDown;
            Showcase2View.PaintSurface += this.ShowcaseView_PaintSurface;
            Showcase3View.MouseDown    += this.ShowcaseView_MouseDown;
            Showcase3View.PaintSurface += this.ShowcaseView_PaintSurface;

            DraggingView.MouseUp      += this.DraggingView_MouseUp;
            DraggingView.MouseMove    += this.DraggingView_MouseMove;
            DraggingView.PaintSurface += this.DraggingView_PaintSurface;

            Redraw();
        }
        private void ShowcaseView_MouseDown(object sender, MouseButtonEventArgs e)
        {
            var showcaseView = sender as SkiaSharp.Views.WPF.SKElement;
            var position     = DpiScaler.ScaleDown(e.GetPosition(showcaseView));
            var map          = Showcase.Maps[int.Parse(showcaseView.Tag.ToString())];
            var hoveredLoc   = GetHoveredLocation(map, position, true);

            if (hoveredLoc is null)
            {
                return;
            }

            var safeHoveredLoc = hoveredLoc.Value;
            var hoveredTile    = map.GetTile(safeHoveredLoc);
            var figure         = hoveredTile?.Parent;

            if (figure is null)
            {
                return;
            }

            Showcase.Pick(figure);
            showcaseView.InvalidateVisual();
            Captured = new(figure);

            DraggingView.Visibility = Visibility.Visible;
            DraggingView.InvalidateVisual();

            ShowcaseClickOffset = Point.Subtract(position, new Point());
            DraggingView_MouseMove(sender, e);
        }
        private void DraggingView_MouseUp(object sender, MouseButtonEventArgs e)
        {
            if (Captured is null || Lost)
            {
                return;
            }

            var draggableLoc = GetHoveredLocation(GameMap, DpiScaler.ScaleDown(Captured.Point), false);

            if (draggableLoc is not null)
            {
                var safeDraggableLoc = draggableLoc.Value;
                if (Captured.Figure.TryPutOnMap(GameMap, safeDraggableLoc))
                {
                    Showcase.Update();
                    Engine.Engine.Score += Captured.Figure.GetTiles().Count();
                    if (Engine.Engine.Score > Properties.Settings.Default.BestScore)
                    {
                        Properties.Settings.Default.BestScore = Engine.Engine.Score;
                        Properties.Settings.Default.Save();
                    }
                    Title = "Счёт: " + Engine.Engine.Score + " / " + Properties.Settings.Default.BestScore;

                    if (DidLose())
                    {
                        Lost          = true;
                        Captured      = null;
                        MouseLocation = new();
                        MapView.InvalidateVisual();
                        DraggingView.InvalidateVisual();
                        Showcase1View.InvalidateVisual();
                        Showcase2View.InvalidateVisual();
                        Showcase3View.InvalidateVisual();
                        return;
                    }
                }
                else
                {
                    Showcase.Return(Captured.Figure);
                }
            }
            else
            {
                Showcase.Return(Captured.Figure);
            }

            Captured                = null;
            MouseLocation           = new();
            DraggingView.Visibility = Visibility.Hidden;
            MapView.InvalidateVisual();
            DraggingView.InvalidateVisual();
            Showcase1View.InvalidateVisual();
            Showcase2View.InvalidateVisual();
            Showcase3View.InvalidateVisual();
        }
        private void MainView_PaintSurface(object sender, SkiaSharp.Views.Desktop.SKPaintSurfaceEventArgs e)
        {
            var canvas = e.Surface.Canvas;

            canvas.Clear(SKColors.White);

            for (int x = 0; x < GameMap.Size; ++x)
            {
                for (int y = 0; y < GameMap.Size; ++y)
                {
                    var skRect = new SKRect(
                        (x * (float)TileSize.Width + TileMargin) * (float)DpiScaler.Scale.Value,
                        (y * (float)TileSize.Height + TileMargin) * (float)DpiScaler.Scale.Value,
                        ((x + 1) * (float)TileSize.Width) * (float)DpiScaler.Scale.Value,
                        ((y + 1) * (float)TileSize.Height) * (float)DpiScaler.Scale.Value);

                    var tile = GameMap.GetTile(x, y);
                    if (tile is null)
                    {
                        Paint.Color = new(0xffd6d6d6);
                    }
                    else
                    {
                        Paint.Color = new(tile.Color);
                    }

                    canvas.DrawRect(skRect, Paint);
                }
            }

            // debug
            if (Captured is not null && !Lost)
            {
                Paint.Color = new(0x44ffffff);

                var draggableLoc = GetHoveredLocation(GameMap, DpiScaler.ScaleDown(Captured.Point), false);
                if (draggableLoc is not null)
                {
                    foreach (var tile in Captured.Figure.GetTiles())
                    {
                        var safeDraggableLoc = draggableLoc.Value;
                        var skRect           = new SKRect(
                            ((safeDraggableLoc.X + tile.X) * (float)TileSize.Width + TileMargin) * (float)DpiScaler.Scale.Value,
                            ((safeDraggableLoc.Y + tile.Y) * (float)TileSize.Height + TileMargin) * (float)DpiScaler.Scale.Value,
                            ((safeDraggableLoc.X + tile.X + 1) * (float)TileSize.Width) * (float)DpiScaler.Scale.Value,
                            ((safeDraggableLoc.Y + tile.Y + 1) * (float)TileSize.Height) * (float)DpiScaler.Scale.Value);

                        canvas.DrawRect(skRect, Paint);
                    }
                }
            }
        }
        private void DraggingView_MouseMove(object sender, MouseEventArgs e)
        {
            var prevLoc  = MouseLocation;
            var position = DpiScaler.ScaleUp(e.GetPosition(DraggingView));

            MouseLocation = position;
            MouseLocation = Point.Add(position, -DpiScaler.ScaleUp(DpiScaler.ScaleUp(ShowcaseClickOffset)));             // the f**k is this

            if (Captured is not null)
            {
                Captured.Move(Point.Subtract(MouseLocation, prevLoc));
                this.DraggingView.InvalidateVisual();

                // debug
                this.MapView.InvalidateVisual();
            }
        }