using Noctalk.UI.Components.Button;
using Noctalk.UI.Components.DropDown;
using Noctalk.UI.Components.Label;
using Noctalk_client.Client.Conversations;
using Noctalk_client.Client.Server_status;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace Noctalk_client.Client.Components.UI.Conversation;

public sealed class Noctalk_conversation_list_item : Border
{
    private static readonly Brush Background_normal = new LinearGradientBrush(Color.FromRgb(7, 15, 27), Color.FromRgb(8, 22, 37), 0);
    private static readonly Brush Background_hover = new LinearGradientBrush(Color.FromRgb(10, 32, 52), Color.FromRgb(13, 45, 72), 0);
    private static readonly Brush Background_selected = new LinearGradientBrush(Color.FromRgb(11, 63, 96), Color.FromRgb(8, 36, 62), 0);
    private static readonly Brush Background_unread = new LinearGradientBrush(Color.FromRgb(24, 22, 58), Color.FromRgb(14, 34, 64), 0);
    private static readonly Brush Border_normal = new SolidColorBrush(Color.FromRgb(18, 62, 93));
    private static readonly Brush Accent_normal = new SolidColorBrush(Color.FromRgb(20, 107, 147));
    private static readonly Brush Accent_selected = new SolidColorBrush(Color.FromRgb(255, 82, 104));
    private static readonly Brush Badge_background = new SolidColorBrush(Color.FromRgb(73, 217, 255));
    private static readonly Brush Badge_text = new SolidColorBrush(Color.FromRgb(5, 9, 18));
    private static readonly Brush Status_checking = new SolidColorBrush(Color.FromRgb(240, 205, 92));
    private static readonly Brush Status_offline = new SolidColorBrush(Color.FromRgb(255, 82, 104));
    private static readonly Brush Status_user_offline = new SolidColorBrush(Color.FromRgb(114, 126, 136));
    private static readonly Brush Status_user_online = new SolidColorBrush(Color.FromRgb(82, 224, 132));
    private static readonly Brush Text_normal = new SolidColorBrush(Color.FromRgb(73, 217, 255));
    private static readonly Brush Text_unread = new SolidColorBrush(Color.FromRgb(185, 243, 255));
    private static readonly Brush Text_selected = new SolidColorBrush(Color.FromRgb(225, 252, 255));
    private readonly Noctalk_label nicknameLabel;
    private readonly Noctalk_label unreadLabel;
    private readonly Border unreadBadge;
    private readonly Border accentBar;
    private readonly Border selectedAccentBar;
    private readonly Border statusDot;
    private readonly Noctalk_button menuButton;
    private int unreadCount;
    private bool isSelected;
    private bool isMenuOpen;

    public Conversation_list_item Conversation { get; }
    public enum__conversation_display_status Current_online_status { get; private set; } = enum__conversation_display_status.Checking;
    public event EventHandler? Conversation_selected;
    public event EventHandler? Clear_messages_requested;
    public event EventHandler? Delete_requested;

    public Noctalk_conversation_list_item(Conversation_list_item The_conversation)
    {
        Conversation = The_conversation;
        Background = Background_normal;
        BorderBrush = Border_normal;
        BorderThickness = new Thickness(1);
        CornerRadius = new CornerRadius(0);
        Padding = new Thickness(0);
        Margin = new Thickness(0);
        HorizontalAlignment = HorizontalAlignment.Stretch;
        Cursor = System.Windows.Input.Cursors.Hand;

        Grid grid = new();
        grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(4) });
        grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(22) });
        grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
        grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(42) });
        grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(4) });

        accentBar = new Border
        {
            Background = Accent_normal,
            CornerRadius = new CornerRadius(0),
            Opacity = 0.7
        };

        selectedAccentBar = new Border
        {
            Background = Accent_selected,
            CornerRadius = new CornerRadius(0),
            Visibility = Visibility.Collapsed
        };

        statusDot = new Border
        {
            Width = 9,
            Height = 9,
            CornerRadius = new CornerRadius(5),
            Background = Status_checking,
            HorizontalAlignment = HorizontalAlignment.Center,
            VerticalAlignment = VerticalAlignment.Center,
            Margin = new Thickness(8, 0, 3, 0)
        };

        nicknameLabel = new Noctalk_label
        {
            Text = Conversation.ToString(),
            Size = Noctalk_label_size.medium,
            Foreground = Text_normal,
            VerticalAlignment = VerticalAlignment.Center,
            Margin = new Thickness(0, 0, 8, 0)
        };

        unreadLabel = new Noctalk_label
        {
            Text = string.Empty,
            Size = Noctalk_label_size.small,
            Foreground = Badge_text,
            HorizontalAlignment = HorizontalAlignment.Center,
            VerticalAlignment = VerticalAlignment.Center
        };

        unreadBadge = new Border
        {
            Child = unreadLabel,
            Background = Badge_background,
            CornerRadius = new CornerRadius(10),
            MinWidth = 22,
            Height = 22,
            Padding = new Thickness(6, 0, 6, 1),
            Visibility = Visibility.Collapsed,
            Margin = new Thickness(4, 0, 6, 0),
            HorizontalAlignment = HorizontalAlignment.Right,
            VerticalAlignment = VerticalAlignment.Center
        };

        menuButton = new Noctalk_button
        {
            Icon = Noctalk_button_icon.Open_dropdown,
            Size = Noctalk_button_size.Custom,
            Width = 26,
            Height = 26,
            Padding = new Thickness(0),
            Margin = new Thickness(4, 6, 6, 6),
            Color = Noctalk_button_color.Blue_O__Blue_R,
            bRounded_corners = true,
            Visibility = Visibility.Hidden
        };
        menuButton.Click += Menu_button__click;

        Grid.SetColumn(accentBar, 0);
        Grid.SetColumn(statusDot, 1);
        Grid.SetColumn(nicknameLabel, 2);
        Grid.SetColumn(unreadBadge, 3);
        Grid.SetColumn(menuButton, 3);
        Grid.SetColumn(selectedAccentBar, 4);
        grid.Children.Add(accentBar);
        grid.Children.Add(statusDot);
        grid.Children.Add(nicknameLabel);
        grid.Children.Add(unreadBadge);
        grid.Children.Add(menuButton);
        grid.Children.Add(selectedAccentBar);
        Child = grid;

        MouseLeftButtonUp += (_, _) => Conversation_selected?.Invoke(this, EventArgs.Empty);
        MouseEnter += (_, _) =>
        {
            UI__conversation_item__apply_trailing_visibility(true);

            if (!isSelected)
            {
                Background = Background_hover;
            }
        };
        MouseLeave += (_, _) =>
        {
            if (!isMenuOpen)
            {
                UI__conversation_item__apply_trailing_visibility(false);
            }

            UI__conversation_item__apply_visual_state();
        };
    }

    public void UI__conversation_item__set_selected(bool Is_selected)
    {
        isSelected = Is_selected;
        UI__conversation_item__apply_visual_state();
    }

    public void UI__conversation_item__increment_unread()
    {
        unreadCount++;
        unreadLabel.Text = unreadCount.ToString();
        UI__conversation_item__apply_trailing_visibility(IsMouseOver || isMenuOpen);
        UI__conversation_item__set_selected(false);
    }

    public void UI__conversation_item__clear_unread()
    {
        unreadCount = 0;
        unreadLabel.Text = string.Empty;
        UI__conversation_item__apply_trailing_visibility(IsMouseOver || isMenuOpen);
    }

    public void UI__conversation_item__set_online_status(enum__conversation_display_status The_status)
    {
        Current_online_status = The_status;
        statusDot.Background = The_status switch
        {
            enum__conversation_display_status.Server_offline => Status_offline,
            enum__conversation_display_status.Peer_offline => Status_user_offline,
            enum__conversation_display_status.Peer_online => Status_user_online,
            _ => Status_checking
        };
    }

    private void Menu_button__click(object sender, RoutedEventArgs e)
    {
        e.Handled = true;
        ContextMenu menu = Noctalk_dropdown_menu.Create();
        MenuItem clearMessagesItem = Noctalk_dropdown_menu.Create_item("Clear messages");
        MenuItem deleteItem = Noctalk_dropdown_menu.Create_item("Delete");
        clearMessagesItem.Click += (_, _) => Clear_messages_requested?.Invoke(this, EventArgs.Empty);
        deleteItem.Click += (_, _) => Delete_requested?.Invoke(this, EventArgs.Empty);
        menu.Items.Add(clearMessagesItem);
        menu.Items.Add(deleteItem);
        menu.PlacementTarget = menuButton;
        menu.Closed += (_, _) =>
        {
            isMenuOpen = false;

            UI__conversation_item__apply_trailing_visibility(IsMouseOver);
        };
        isMenuOpen = true;
        UI__conversation_item__apply_trailing_visibility(true);
        menu.IsOpen = true;
    }

    private void UI__conversation_item__apply_trailing_visibility(bool Show_menu_button)
    {
        menuButton.Visibility = Show_menu_button ? Visibility.Visible : Visibility.Hidden;
        unreadBadge.Visibility = !Show_menu_button && unreadCount > 0 ? Visibility.Visible : Visibility.Collapsed;
    }

    private void UI__conversation_item__apply_visual_state()
    {
        bool hasUnread = unreadCount > 0;
        Background = isSelected ? Background_selected : hasUnread ? Background_unread : Background_normal;
        BorderBrush = Border_normal;
        BorderThickness = isSelected ? new Thickness(0) : new Thickness(1);
        accentBar.Background = Accent_normal;
        accentBar.Opacity = isSelected ? 0 : hasUnread ? 0.95 : 0.7;
        selectedAccentBar.Visibility = isSelected ? Visibility.Visible : Visibility.Collapsed;
        nicknameLabel.Foreground = isSelected ? Text_selected : hasUnread ? Text_unread : Text_normal;
        nicknameLabel.FontWeight = isSelected ? FontWeights.ExtraBold : FontWeights.Bold;
    }
}
