//  
//   Rebex Sample Code License
// 
//   Copyright 2025, REBEX CR s.r.o.
//   All rights reserved.
//   https://www.rebex.net/
// 
//   Permission to use, copy, modify, and/or distribute this software for any
//   purpose with or without fee is hereby granted.
// 
//   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
//   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
//   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
//   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
//   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
//   OTHER DEALINGS IN THE SOFTWARE.
// 

using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using Rebex.IO.Compression;

namespace Rebex.Samples
{
    /// <summary>
    /// A dialog that asks for action when a problem occurs.
    /// </summary>
    public partial class ProblemDetectedDialog : Form
    {
        // event arguments
        private ZipProblemDetectedEventArgs _arguments;

        // list of problem types the user chose to skip
        private readonly Dictionary<ArchiveProblemType, object> _skipProblemTypes = new Dictionary<ArchiveProblemType, object>();

        // true if the user chose to overwrite all existing files
        private bool _overwriteAll;

        // true if the user chose to overwrite all older files
        private bool _overwriteOlder;

        // true if the user chose to overwrite all files with a different size
        private bool _overwriteDifferentSize;

        // true if the user chose to overwrite all files with a different checksum
        private bool _overwriteDifferentChecksum;

        /// <summary>
        /// Initializes a new instance of the dialog.
        /// </summary>
        public ProblemDetectedDialog()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Shows the form as a modal dialog box.
        /// The form's buttons are enabled according to the possible actions taken from the given event argument.
        /// </summary>
        /// <param name="owner">Owner of the dialog.</param>
        /// <param name="e">Event argument describing the problem type.</param>
        public void ShowDialog(Control owner, ZipProblemDetectedEventArgs e)
        {
            // if the user chose to skip this problem type, skip it
            if (_skipProblemTypes.ContainsKey(e.ProblemType))
            {
                e.Action = ArchiveProblemActions.Skip;
                return;
            }

            // if the problem is FileExists check, whether the user have chosen any default action already
            if (e.ProblemType == ArchiveProblemType.FileExists)
            {
                if (_overwriteAll)
                {
                    e.Action = ArchiveProblemActions.Overwrite;
                    return;
                }

                if (_overwriteDifferentSize)
                {
                    e.Action = ArchiveProblemActions.OverwriteIfDifferentSize;
                    return;
                }

                if (_overwriteDifferentChecksum)
                {
                    e.Action = ArchiveProblemActions.OverwriteIfDifferentChecksum;
                    return;
                }

                if (_overwriteOlder)
                {
                    e.Action = ArchiveProblemActions.OverwriteIfOlder;
                    return;
                }

                // format the text according to SftpTransferState (Downloading or Uploading)
                string messageFormat = "Overwrite file: {0}\n    {1} Bytes, {2}\n\nwith file: {3}\n    {4} Bytes, {5}";
                if (e.Operation == ArchiveOperation.Extract)
                {
                    lblMessage.Text = string.Format(messageFormat,
                        e.ExternalItemPath, e.ExternalItemLength, e.ExternalItemLastWriteTime,
                        e.ArchiveItemPath, e.ArchiveItemLength, e.ArchiveItemLastWriteTime);
                }
                else
                {
                    lblMessage.Text = string.Format(messageFormat,
                        e.ArchiveItemPath, e.ArchiveItemLength, e.ArchiveItemLastWriteTime,
                        e.ExternalItemPath, e.ExternalItemLength, e.ExternalItemLastWriteTime);
                }

                lblMessage.TextAlign = ContentAlignment.MiddleLeft;
            }
            else
            {
                lblMessage.Text = e.Exception.Message;
                lblMessage.TextAlign = ContentAlignment.MiddleCenter;
            }

            // store the event arguments for later use at button click handler
            _arguments = e;

            // only enable buttons that represent a possible action
            btnCancel.Enabled = e.IsActionPossible(ArchiveProblemActions.Cancel);
            btnSkip.Enabled = e.IsActionPossible(ArchiveProblemActions.Skip);
            btnSkipAll.Enabled = e.IsActionPossible(ArchiveProblemActions.Skip);
            btnRetry.Enabled = e.IsActionPossible(ArchiveProblemActions.Retry);
            btnRename.Enabled = e.IsActionPossible(ArchiveProblemActions.Rename);
            btnOverwrite.Enabled = e.IsActionPossible(ArchiveProblemActions.Overwrite);
            btnOverwriteAll.Enabled = e.IsActionPossible(ArchiveProblemActions.Overwrite);
            btnOverwriteOlder.Enabled = e.IsActionPossible(ArchiveProblemActions.OverwriteIfOlder);
            btnOverwriteDiffSize.Enabled = e.IsActionPossible(ArchiveProblemActions.OverwriteIfDifferentSize);
            btnOverwriteDiffChecksum.Enabled = e.IsActionPossible(ArchiveProblemActions.OverwriteIfDifferentChecksum);
            btnFollowLink.Enabled = e.IsActionPossible(ArchiveProblemActions.FollowLink);

            // select default action button
            SetDefaultActionButton(e.Action);

            ShowDialog(owner);
        }

        /// <summary>
        /// Selects the default button according to the default action.
        /// </summary>
        /// <param name="action">Default problem action.</param>
        private void SetDefaultActionButton(ArchiveProblemActions action)
        {
            switch (action)
            {
                case ArchiveProblemActions.ThrowException: 
                case ArchiveProblemActions.Cancel: btnCancel.Select(); break;
                case ArchiveProblemActions.Skip: btnSkipAll.Select(); break;
                case ArchiveProblemActions.Retry: btnRetry.Select(); break;
                case ArchiveProblemActions.Rename: btnRename.Select(); break;
                case ArchiveProblemActions.Overwrite: btnOverwriteAll.Select(); break;
                case ArchiveProblemActions.OverwriteIfOlder: btnOverwriteOlder.Select(); break;
                case ArchiveProblemActions.OverwriteIfDifferentSize: btnOverwriteDiffSize.Select(); break;
                case ArchiveProblemActions.OverwriteIfDifferentChecksum: btnOverwriteDiffChecksum.Select(); break;
                case ArchiveProblemActions.FollowLink: btnFollowLink.Select(); break;
            }
        }

        private void btnCancel_Click(object sender, System.EventArgs e)
        {
            _arguments.Action = ArchiveProblemActions.Cancel;
            Close();
        }

        private void btnSkip_Click(object sender, System.EventArgs e)
        {
            _arguments.Action = ArchiveProblemActions.Skip;
            Close();
        }

        private void btnSkipAll_Click(object sender, System.EventArgs e)
        {
            // add the problem to the list of automatically skipped problems
            _skipProblemTypes.Add(_arguments.ProblemType, null);

            _arguments.Action = ArchiveProblemActions.Skip;
            Close();
        }

        private void btnRetry_Click(object sender, System.EventArgs e)
        {
            _arguments.Action = ArchiveProblemActions.Retry;
            Close();
        }

        private void btnRename_Click(object sender, System.EventArgs e)
        {
            // get the filename
            string fileName = Path.GetFileName(_arguments.ExternalItemPath);

            // initialize the renaming form
            NewNameDialog dialog = new NewNameDialog(fileName, true);

            // show the form
            DialogResult result = dialog.ShowDialog(this);

            // check whether the user clicked OK
            if (result != DialogResult.OK)
                return;

            // set the appropriate action and new name to the event arguments
            _arguments.Action = ArchiveProblemActions.Rename;
            _arguments.NewName = dialog.NewName;
            Close();
        }

        private void btnOverwrite_Click(object sender, System.EventArgs e)
        {
            _arguments.Action = ArchiveProblemActions.Overwrite;
            Close();
        }

        private void btnOverwriteAll_Click(object sender, System.EventArgs e)
        {
            _arguments.Action = ArchiveProblemActions.Overwrite;
            _overwriteAll = true;
            Close();
        }

        private void btnOverwriteOlder_Click(object sender, System.EventArgs e)
        {
            _arguments.Action = ArchiveProblemActions.OverwriteIfOlder;
            _overwriteOlder = true;
            Close();
        }

        private void btnOverwriteDiffSize_Click(object sender, System.EventArgs e)
        {
            _arguments.Action = ArchiveProblemActions.OverwriteIfDifferentSize;
            _overwriteDifferentSize = true;
            Close();
        }

        private void btnOverwriteDiffChecksum_Click(object sender, EventArgs e)
        {
            _arguments.Action = ArchiveProblemActions.OverwriteIfDifferentChecksum;
            _overwriteDifferentChecksum = true;
            Close();
        }

        private void btnFollowLink_Click(object sender, System.EventArgs e)
        {
            _arguments.Action = ArchiveProblemActions.FollowLink;
            Close();
        }

        
    }
}