using Sunfish.Config;

namespace Sunfish.WinForms;

/// <summary>
/// Alta o edicion de un share con el aspecto de la 2.0: estrecho y vertical, etiqueta encima de
/// cada campo, los obligatorios en amarillo claro y el aviso en un recuadro amarillo.
/// </summary>
internal sealed class ShareDialog : Form
{
    private static readonly Color MandatoryBack = Color.FromArgb(255, 252, 220);
    private const int FieldWidth = 260;

    private readonly SunfishConfig _config;
    private readonly string? _originalName;
    private readonly TextBox _name = new() { Width = FieldWidth - 70, BackColor = MandatoryBack };
    private readonly CheckBox _enabled = new() { AutoSize = true, Margin = new Padding(8, 4, 0, 0) };
    private readonly TextBox _location = new() { Width = FieldWidth, BackColor = MandatoryBack };
    private readonly TextBox _path = new() { Width = FieldWidth - 30, BackColor = MandatoryBack };
    private readonly TextBox _index = new() { Width = FieldWidth };
    private readonly CheckBox _listing = new() { AutoSize = true };
    private readonly CheckBox _upload = new() { AutoSize = true };
    private readonly CheckBox _overwrite = new() { AutoSize = true };
    private readonly CheckBox _rename = new() { AutoSize = true };
    private readonly CheckBox _delete = new() { AutoSize = true };
    private readonly CheckBox _zip = new() { AutoSize = true };
    private readonly CheckedListBox _users = new() { Width = FieldWidth, Height = 64, CheckOnClick = true, IntegralHeight = false };
    private readonly Label _warning = new()
    {
        AutoSize = true, MaximumSize = new Size(FieldWidth, 0), BackColor = Color.FromArgb(240, 230, 160),
        BorderStyle = BorderStyle.FixedSingle, Padding = new Padding(3), Margin = new Padding(3, 8, 3, 3),
    };

    public ShareConfig Result { get; }

    public ShareDialog(ShareConfig share, SunfishConfig config, string? originalName)
    {
        Result = share;
        _config = config;
        _originalName = originalName;

        SuspendLayout();
        AutoScaleDimensions = new SizeF(96F, 96F);
        AutoScaleMode = AutoScaleMode.Dpi;
        Text = originalName is null ? Texts.NewShare : Texts.EditShareTitle(originalName);
        FormBorderStyle = FormBorderStyle.FixedDialog;
        MaximizeBox = MinimizeBox = false;
        ShowInTaskbar = false;
        StartPosition = FormStartPosition.CenterParent;
        AutoSize = true;
        AutoSizeMode = AutoSizeMode.GrowAndShrink;
        Padding = new Padding(8, 6, 8, 8);

        _enabled.Text = Texts.Active;
        _listing.Text = Strings.OptListing;
        _upload.Text = Strings.OptUpload;
        _overwrite.Text = Strings.OptOverwrite;
        _rename.Text = Strings.OptRename;
        _delete.Text = Strings.OptDelete;
        _zip.Text = Strings.OptZip;

        _name.Text = share.Name;
        _location.Text = share.Location;
        _path.Text = share.Path;
        _index.Text = share.Index;
        _enabled.Checked = share.Enabled;
        _listing.Checked = share.Listing;
        _upload.Checked = share.Upload;
        _overwrite.Checked = share.Overwrite;
        _rename.Checked = share.Rename;
        _delete.Checked = share.Delete;
        _zip.Checked = share.Zip;
        foreach (var user in config.Users)
            _users.Items.Add(user.Name, share.Users.Contains(user.Name, StringComparer.OrdinalIgnoreCase));

        var browse = new Button { Text = "...", Size = new Size(26, _path.Height + 2), Margin = new Padding(2, 2, 0, 0), UseVisualStyleBackColor = true };
        browse.Click += (_, _) => Browse();

        // El formulario se ajusta al contenido: el panel va en la esquina del relleno (Padding solo
        // lo respetan los controles acoplados) y el relleno derecho/inferior lo anade AutoSize.
        var main = new FlowLayoutPanel
        {
            FlowDirection = FlowDirection.TopDown, AutoSize = true, WrapContents = false,
            Location = new Point(Padding.Left, Padding.Top), Margin = new Padding(0),
        };
        main.Controls.Add(Caption(Strings.FieldName));
        main.Controls.Add(Row(_name, _enabled));
        main.Controls.Add(Caption(Strings.FieldLocation));
        main.Controls.Add(_location);
        main.Controls.Add(Caption(Strings.FieldPath));
        main.Controls.Add(Row(_path, browse));
        main.Controls.Add(Caption(Strings.FieldIndex));
        main.Controls.Add(_index);
        main.Controls.Add(new Panel { Height = 6, Width = 1 });
        foreach (var check in new[] { _listing, _upload, _overwrite, _rename, _delete, _zip })
        {
            check.Margin = new Padding(14, 2, 3, 2);
            main.Controls.Add(check);
        }
        if (config.Users.Count > 0)
        {
            main.Controls.Add(Caption(Texts.AllowedUsers));
            main.Controls.Add(_users);
        }
        main.Controls.Add(_warning);

        var ok = new Button { Text = Texts.Ok, Size = new Size(80, 25), UseVisualStyleBackColor = true };
        ok.Click += (_, _) => Accept();
        var cancel = new Button { Text = Texts.Cancel, Size = new Size(80, 25), DialogResult = DialogResult.Cancel, UseVisualStyleBackColor = true };
        var buttons = new FlowLayoutPanel { FlowDirection = FlowDirection.RightToLeft, Width = FieldWidth + 6, Height = 25, Margin = new Padding(0, 10, 0, 0) };
        ok.Margin = new Padding(3, 0, 3, 0);
        cancel.Margin = new Padding(3, 0, 3, 0);
        buttons.Controls.AddRange([cancel, ok]);
        main.Controls.Add(buttons);
        AcceptButton = ok;
        CancelButton = cancel;

        Controls.Add(main);
        ResumeLayout(false);
        PerformLayout();

        _upload.CheckedChanged += (_, _) => UpdateWarning();
        _listing.CheckedChanged += (_, _) => UpdateWarning();
        UpdateWarning();
    }

    private static Label Caption(string text) =>
        new() { Text = text + ":", AutoSize = true, Margin = new Padding(3, 6, 3, 1) };

    private static FlowLayoutPanel Row(params Control[] controls)
    {
        var row = new FlowLayoutPanel { AutoSize = true, WrapContents = false, Margin = new Padding(0) };
        row.Controls.AddRange(controls);
        return row;
    }

    private void Browse()
    {
        using var picker = new FolderBrowserDialog { SelectedPath = _path.Text, UseDescriptionForTitle = true, Description = Strings.FieldPath };
        if (picker.ShowDialog(this) != DialogResult.OK)
            return;
        _path.Text = picker.SelectedPath;
        if (_name.Text.Length == 0)
        {
            _name.Text = ShareSettings.SuggestName(_config, Path.GetFileName(Path.TrimEndingDirectorySeparator(picker.SelectedPath)));
            _location.Text = ShareSettings.SuggestLocation(_config, _name.Text);
        }
    }

    private void UpdateWarning()
    {
        bool show = _upload.Checked && _listing.Checked;
        _warning.Text = show ? Strings.WarnUploadListing : "";
        _warning.Visible = show;
    }

    private void Accept()
    {
        var s = Result;
        s.Name = _name.Text.Trim();
        s.Location = _location.Text.Trim();
        s.Path = _path.Text.Trim();
        s.Index = _index.Text.Trim();
        s.Enabled = _enabled.Checked;
        s.Listing = _listing.Checked;
        s.Upload = _upload.Checked;
        s.Overwrite = _overwrite.Checked;
        s.Rename = _rename.Checked;
        s.Delete = _delete.Checked;
        s.Zip = _zip.Checked;
        if (_config.Users.Count > 0)
            s.Users = _users.CheckedItems.Cast<string>().ToList();
        if (ShareSettings.Validate(_config, s, _originalName) is { } problem)
        {
            MessageBox.Show(this, problem, Text, MessageBoxButtons.OK, MessageBoxIcon.Warning);
            return;
        }
        DialogResult = DialogResult.OK;
    }
}
