using v2rayN.Desktop.Base;

namespace v2rayN.Desktop.Views;

public partial class AddGroupServerWindow : WindowBase<AddGroupServerViewModel>
{
    public AddGroupServerWindow()
    {
        InitializeComponent();

        Loaded += Window_Loaded;
        btnCancel.Click += (s, e) => Close();
        lstChild.SelectionChanged += LstChild_SelectionChanged;
        tabControl.SelectionChanged += TabControl_SelectionChanged;

        cmbCoreType.ItemsSource = Global.CoreTypes;
        cmbPolicyGroupType.ItemsSource = new List<string>
        {
            ResUI.TbLeastPing,
            ResUI.TbFallback,
            ResUI.TbRandom,
            ResUI.TbRoundRobin,
            ResUI.TbLeastLoad,
        };
        cmbFilter.ItemsSource = Global.PolicyGroupDefaultFilterList;

        this.WhenActivated(disposables =>
        {
            this.WhenAnyValue(v => v.ViewModel.SelectedSource)
                .KeepNotNull()
                .Subscribe(InitializeData)
                .DisposeWith(disposables);

            this.Bind(ViewModel, vm => vm.SelectedSource.Remarks, v => v.txtRemarks.Text).DisposeWith(disposables);
            this.Bind(ViewModel, vm => vm.CoreType, v => v.cmbCoreType.SelectedValue).DisposeWith(disposables);
            this.Bind(ViewModel, vm => vm.PolicyGroupType, v => v.cmbPolicyGroupType.SelectedValue).DisposeWith(disposables);
            //this.OneWayBind(ViewModel, vm => vm.SubItems, v => v.cmbSubChildItems.ItemsSource).DisposeWith(disposables);
            this.Bind(ViewModel, vm => vm.SelectedSubItem, v => v.cmbSubChildItems.SelectedItem).DisposeWith(disposables);
            this.Bind(ViewModel, vm => vm.Filter, v => v.cmbFilter.Text).DisposeWith(disposables);

            this.Bind(ViewModel, vm => vm.SelectedChild, v => v.lstChild.SelectedItem).DisposeWith(disposables);

            this.BindCommand(ViewModel, vm => vm.AddCmd, v => v.menuAddChildServer).DisposeWith(disposables);
            this.BindCommand(ViewModel, vm => vm.RemoveCmd, v => v.menuRemoveChildServer).DisposeWith(disposables);
            this.BindCommand(ViewModel, vm => vm.MoveTopCmd, v => v.menuMoveTop).DisposeWith(disposables);
            this.BindCommand(ViewModel, vm => vm.MoveUpCmd, v => v.menuMoveUp).DisposeWith(disposables);
            this.BindCommand(ViewModel, vm => vm.MoveDownCmd, v => v.menuMoveDown).DisposeWith(disposables);
            this.BindCommand(ViewModel, vm => vm.MoveBottomCmd, v => v.menuMoveBottom).DisposeWith(disposables);

            this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
        });

        // Context menu actions that require custom logic (Add, SelectAll)
        menuSelectAllChild.Click += (s, e) => lstChild.SelectAll();

        // Keyboard shortcuts when focus is within grid
        AddHandler(KeyDownEvent, AddGroupServerWindow_KeyDown, RoutingStrategies.Tunnel);
        lstChild.LoadingRow += LstChild_LoadingRow;
    }

    private void InitializeData(ProfileItem profileItem)
    {
        switch (profileItem.ConfigType)
        {
            case EConfigType.PolicyGroup:
                Title = ResUI.TbConfigTypePolicyGroup;
                break;

            case EConfigType.ProxyChain:
                Title = ResUI.TbConfigTypeProxyChain;
                gridPolicyGroup.IsVisible = false;
                if (tabControl.Items.Count > 0)
                {
                    tabControl.Items.RemoveAt(0);
                }
                break;
        }
    }

    private void LstChild_LoadingRow(object? sender, DataGridRowEventArgs e)
    {
        e.Row.Header = $" {e.Row.Index + 1}";
    }

    private void Window_Loaded(object? sender, RoutedEventArgs e)
    {
        txtRemarks.Focus();
    }

    private void AddGroupServerWindow_KeyDown(object? sender, KeyEventArgs e)
    {
        if (!lstChild.IsKeyboardFocusWithin)
        {
            return;
        }

        if ((e.KeyModifiers & (KeyModifiers.Control | KeyModifiers.Meta)) != 0)
        {
            if (e.Key == Key.A)
            {
                lstChild.SelectAll();
                e.Handled = true;
            }
        }
        else
        {
            switch (e.Key)
            {
                case Key.T:
                    ViewModel?.MoveServer(EMove.Top);
                    e.Handled = true;
                    break;

                case Key.U:
                    ViewModel?.MoveServer(EMove.Up);
                    e.Handled = true;
                    break;

                case Key.D:
                    ViewModel?.MoveServer(EMove.Down);
                    e.Handled = true;
                    break;

                case Key.B:
                    ViewModel?.MoveServer(EMove.Bottom);
                    e.Handled = true;
                    break;

                case Key.Delete:
                case Key.Back:
                    ViewModel?.ChildRemoveAsync();
                    e.Handled = true;
                    break;
            }
        }
    }

    private void LstChild_SelectionChanged(object? sender, SelectionChangedEventArgs e)
    {
        if (ViewModel != null)
        {
            ViewModel.SelectedChildren = lstChild.SelectedItems.Cast<ProfileItem>().ToList();
        }
    }

    private async void TabControl_SelectionChanged(object? sender, SelectionChangedEventArgs e)
    {
        try
        {
            if (e.Source is not TabControl tc)
            {
                return;
            }
            if (!(tc.SelectedIndex == tc.Items.Count - 1 && tc.Items.Count > 0))
            {
                return;
            }
            if (ViewModel == null)
            {
                return;
            }

            await ViewModel.UpdatePreviewList();
        }
        catch
        {
            // ignored
        }
    }
}
