//  
//   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.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;

using Rebex.IO;
using Rebex.Net;

namespace Rebex.Samples
{
    /// <summary>
    /// Problem handling form.
    /// </summary>
    public class ProblemDetectedForm : System.Windows.Forms.Form
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.Container components = null;

        private System.Windows.Forms.Label lblMessage;
        private System.Windows.Forms.Button btnCancel;
        private System.Windows.Forms.Button btnSkip;
        private System.Windows.Forms.Button btnRename;
        private System.Windows.Forms.Button btnRetry;
        private System.Windows.Forms.Button btnOverwrite;
        private System.Windows.Forms.Button btnOverwriteAll;
        private System.Windows.Forms.Button btnOverwriteOlder;
        private System.Windows.Forms.Button btnOverwriteDiffSize;
        private System.Windows.Forms.Button btnSkipAll;
        private System.Windows.Forms.Button btnFollowLink;
        private System.Windows.Forms.Button btnResume;

        // event arguments
        private ProblemDetectedEventArgs _arguments;

        // list of problem types the user chose to skip
        private readonly Hashtable _skipProblemTypes = new Hashtable();

        // 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;
        private Button btnOverwriteDiffChecksum;

        // 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;

        public ProblemDetectedForm()
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();
        }

        /// <summary>
        /// Initialize the form for using it again in new batch transfer.
        /// </summary>
        /// <remarks>
        /// Clears the user's chosen default actions.
        /// </remarks>
        public void Initialize()
        {
            _skipProblemTypes.Clear();
            _overwriteAll = false;
            _overwriteOlder = false;
            _overwriteDifferentSize = false;
            _overwriteDifferentChecksum = false;
        }

        /// <summary>
        /// Shows the form as a modal dialog box.
        /// The form's buttons are shown according to possible actions taken from the given event argument.
        /// </summary>
        /// <param name="e">Event argument describing the type of a problem.</param>
        public void ShowModal(Control form, ProblemDetectedEventArgs e)
        {
            if (e == null)
                throw new ArgumentNullException("e");

            // if the user chose to skip this problem type, skip it
            if (_skipProblemTypes.ContainsKey(e.ProblemType))
            {
                e.Skip();
                return;
            }

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

                if (_overwriteDifferentSize)
                {
                    e.Overwrite(OverwriteCondition.SizeDiffers);
                    return;
                }

                if (_overwriteDifferentChecksum)
                {
                    e.Overwrite(OverwriteCondition.ChecksumDiffers);
                    return;
                }

                if (_overwriteOlder)
                {
                    e.Overwrite(OverwriteCondition.Older);
                    return;
                }

                // format the text according to action in progress (Downloading or Uploading)
                string messageFormat = "Overwrite file: {0}\n\t{1} Bytes, {2}\n\nwith file: {3}\n\t{4} Bytes, {5}";
                if (e.Action == TransferAction.Downloading)
                {
                    lblMessage.Text = string.Format(messageFormat,
                        e.LocalPath, e.LocalItem.Length, e.LocalItem.LastWriteTime,
                        e.RemotePath, e.RemoteItem.Length, e.RemoteItem.LastWriteTime);
                }
                else
                {
                    lblMessage.Text = string.Format(messageFormat,
                        e.RemotePath, e.RemoteItem.Length, e.RemoteItem.LastWriteTime,
                        e.LocalPath, e.LocalItem.Length, e.LocalItem.LastWriteTime);
                }

                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.IsReactionPossible(TransferProblemReaction.Cancel);
            btnSkip.Enabled = e.IsReactionPossible(TransferProblemReaction.Skip);
            btnSkipAll.Enabled = e.IsReactionPossible(TransferProblemReaction.Skip);
            btnRetry.Enabled = e.IsReactionPossible(TransferProblemReaction.Retry);
            btnRename.Enabled = e.IsReactionPossible(TransferProblemReaction.Rename);
            btnOverwrite.Enabled = e.IsReactionPossible(TransferProblemReaction.Overwrite);
            btnOverwriteAll.Enabled = e.IsReactionPossible(TransferProblemReaction.Overwrite);
            btnOverwriteOlder.Enabled = e.IsReactionPossible(TransferProblemReaction.Overwrite);
            btnOverwriteDiffSize.Enabled = e.IsReactionPossible(TransferProblemReaction.Overwrite);
            btnOverwriteDiffChecksum.Enabled = e.IsOverwriteConditionPossible(OverwriteCondition.ChecksumDiffers);
            btnFollowLink.Enabled = e.IsReactionPossible(TransferProblemReaction.FollowLink);
            btnResume.Enabled = e.IsReactionPossible(TransferProblemReaction.Resume);

            // select default action button
            SetDefaultActionButton(e);

            ShowDialog(form);
        }

        /// <summary>
        /// Selects the button according to default action.
        /// </summary>
        /// <param name="e">Default action.</param>
        private void SetDefaultActionButton(ProblemDetectedEventArgs e)
        {
            switch (e.Reaction)
            {
                case TransferProblemReaction.Cancel: btnCancel.Select(); break;
                case TransferProblemReaction.Fail: btnCancel.Select(); break;
                case TransferProblemReaction.Skip: btnSkipAll.Select(); break;
                case TransferProblemReaction.Retry: btnRetry.Select(); break;
                case TransferProblemReaction.Rename: btnRename.Select(); break;
                case TransferProblemReaction.FollowLink: btnFollowLink.Select(); break;
                case TransferProblemReaction.Resume: btnResume.Select(); break;
                case TransferProblemReaction.Overwrite:
                    switch (e.OverwriteCondition)
                    {
                        case OverwriteCondition.None: btnOverwriteAll.Select(); break;
                        case OverwriteCondition.Older: btnOverwriteOlder.Select(); break;
                        case OverwriteCondition.SizeDiffers: btnOverwriteDiffSize.Select(); break;
                        case OverwriteCondition.ChecksumDiffers: btnOverwriteDiffChecksum.Select(); break;
                    }
                    break;
            }
        }

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.btnCancel = new System.Windows.Forms.Button();
            this.btnSkip = new System.Windows.Forms.Button();
            this.btnRename = new System.Windows.Forms.Button();
            this.btnRetry = new System.Windows.Forms.Button();
            this.btnOverwrite = new System.Windows.Forms.Button();
            this.btnOverwriteAll = new System.Windows.Forms.Button();
            this.btnOverwriteOlder = new System.Windows.Forms.Button();
            this.btnOverwriteDiffSize = new System.Windows.Forms.Button();
            this.btnSkipAll = new System.Windows.Forms.Button();
            this.btnFollowLink = new System.Windows.Forms.Button();
            this.lblMessage = new System.Windows.Forms.Label();
            this.btnResume = new System.Windows.Forms.Button();
            this.btnOverwriteDiffChecksum = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // btnCancel
            // 
            this.btnCancel.Location = new System.Drawing.Point(8, 112);
            this.btnCancel.Name = "btnCancel";
            this.btnCancel.Size = new System.Drawing.Size(157, 24);
            this.btnCancel.TabIndex = 0;
            this.btnCancel.Text = "&Cancel";
            this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
            // 
            // btnSkip
            // 
            this.btnSkip.Location = new System.Drawing.Point(349, 80);
            this.btnSkip.Name = "btnSkip";
            this.btnSkip.Size = new System.Drawing.Size(179, 24);
            this.btnSkip.TabIndex = 1;
            this.btnSkip.Text = "&Skip";
            this.btnSkip.Click += new System.EventHandler(this.btnSkip_Click);
            // 
            // btnRename
            // 
            this.btnRename.Location = new System.Drawing.Point(8, 144);
            this.btnRename.Name = "btnRename";
            this.btnRename.Size = new System.Drawing.Size(157, 24);
            this.btnRename.TabIndex = 2;
            this.btnRename.Text = "&Rename...";
            this.btnRename.Click += new System.EventHandler(this.btnRename_Click);
            // 
            // btnRetry
            // 
            this.btnRetry.Location = new System.Drawing.Point(8, 176);
            this.btnRetry.Name = "btnRetry";
            this.btnRetry.Size = new System.Drawing.Size(157, 24);
            this.btnRetry.TabIndex = 3;
            this.btnRetry.Text = "Re&try";
            this.btnRetry.Click += new System.EventHandler(this.btnRetry_Click);
            // 
            // btnOverwrite
            // 
            this.btnOverwrite.Location = new System.Drawing.Point(8, 80);
            this.btnOverwrite.Name = "btnOverwrite";
            this.btnOverwrite.Size = new System.Drawing.Size(157, 24);
            this.btnOverwrite.TabIndex = 4;
            this.btnOverwrite.Text = "&Overwrite";
            this.btnOverwrite.Click += new System.EventHandler(this.btnOverwrite_Click);
            // 
            // btnOverwriteAll
            // 
            this.btnOverwriteAll.Location = new System.Drawing.Point(180, 80);
            this.btnOverwriteAll.Name = "btnOverwriteAll";
            this.btnOverwriteAll.Size = new System.Drawing.Size(157, 24);
            this.btnOverwriteAll.TabIndex = 5;
            this.btnOverwriteAll.Text = "Overwrite &All";
            this.btnOverwriteAll.Click += new System.EventHandler(this.btnOverwriteAll_Click);
            // 
            // btnOverwriteOlder
            // 
            this.btnOverwriteOlder.Location = new System.Drawing.Point(180, 112);
            this.btnOverwriteOlder.Name = "btnOverwriteOlder";
            this.btnOverwriteOlder.Size = new System.Drawing.Size(157, 24);
            this.btnOverwriteOlder.TabIndex = 6;
            this.btnOverwriteOlder.Text = "Overwrite All Ol&der";
            this.btnOverwriteOlder.Click += new System.EventHandler(this.btnOverwriteOlder_Click);
            // 
            // btnOverwriteDiffSize
            // 
            this.btnOverwriteDiffSize.Location = new System.Drawing.Point(180, 144);
            this.btnOverwriteDiffSize.Name = "btnOverwriteDiffSize";
            this.btnOverwriteDiffSize.Size = new System.Drawing.Size(157, 24);
            this.btnOverwriteDiffSize.TabIndex = 7;
            this.btnOverwriteDiffSize.Text = "Overwrite &If Size Differs";
            this.btnOverwriteDiffSize.Click += new System.EventHandler(this.btnOverwriteDiffSize_Click);
            // 
            // btnSkipAll
            // 
            this.btnSkipAll.Location = new System.Drawing.Point(349, 112);
            this.btnSkipAll.Name = "btnSkipAll";
            this.btnSkipAll.Size = new System.Drawing.Size(179, 24);
            this.btnSkipAll.TabIndex = 8;
            this.btnSkipAll.Text = "S&kip All";
            this.btnSkipAll.Click += new System.EventHandler(this.btnSkipAll_Click);
            // 
            // btnFollowLink
            // 
            this.btnFollowLink.Location = new System.Drawing.Point(180, 176);
            this.btnFollowLink.Name = "btnFollowLink";
            this.btnFollowLink.Size = new System.Drawing.Size(157, 24);
            this.btnFollowLink.TabIndex = 9;
            this.btnFollowLink.Text = "Follow &Link";
            this.btnFollowLink.Click += new System.EventHandler(this.btnFollowLink_Click);
            // 
            // lblMessage
            // 
            this.lblMessage.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.lblMessage.Location = new System.Drawing.Point(8, 8);
            this.lblMessage.Name = "lblMessage";
            this.lblMessage.Size = new System.Drawing.Size(530, 64);
            this.lblMessage.TabIndex = 11;
            this.lblMessage.Text = "Message";
            this.lblMessage.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
            // 
            // btnResume
            // 
            this.btnResume.Location = new System.Drawing.Point(349, 176);
            this.btnResume.Name = "btnResume";
            this.btnResume.Size = new System.Drawing.Size(179, 24);
            this.btnResume.TabIndex = 12;
            this.btnResume.Text = "Resume";
            this.btnResume.Click += new System.EventHandler(this.btnResume_Click);
            // 
            // btnOverwriteDiffChecksum
            // 
            this.btnOverwriteDiffChecksum.Location = new System.Drawing.Point(349, 144);
            this.btnOverwriteDiffChecksum.Name = "btnOverwriteDiffChecksum";
            this.btnOverwriteDiffChecksum.Size = new System.Drawing.Size(179, 24);
            this.btnOverwriteDiffChecksum.TabIndex = 13;
            this.btnOverwriteDiffChecksum.Text = "Overwrite If Checksum Differs";
            this.btnOverwriteDiffChecksum.Click += new System.EventHandler(this.btnOverwriteDiffChecksum_Click);
            // 
            // ProblemDetectedForm
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(540, 208);
            this.Controls.Add(this.btnOverwriteDiffChecksum);
            this.Controls.Add(this.btnResume);
            this.Controls.Add(this.lblMessage);
            this.Controls.Add(this.btnFollowLink);
            this.Controls.Add(this.btnSkipAll);
            this.Controls.Add(this.btnOverwriteDiffSize);
            this.Controls.Add(this.btnOverwriteOlder);
            this.Controls.Add(this.btnOverwriteAll);
            this.Controls.Add(this.btnOverwrite);
            this.Controls.Add(this.btnRetry);
            this.Controls.Add(this.btnRename);
            this.Controls.Add(this.btnSkip);
            this.Controls.Add(this.btnCancel);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
            this.MaximizeBox = false;
            this.MinimizeBox = false;
            this.Name = "ProblemDetectedForm";
            this.ShowInTaskbar = false;
            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
            this.Text = "Transfer Problem Detected";
            this.ResumeLayout(false);

        }
        #endregion

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

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

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

            _arguments.Skip();
            Close();
        }

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

        private void btnRename_Click(object sender, System.EventArgs e)
        {
            // initialize the renaming form
            NewNameForm formNewName = new NewNameForm();

            // set the current file name
            string oldName = Path.GetFileName(_arguments.LocalPath);
            formNewName.FileName = oldName;

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

            // get the new name
            string newName = formNewName.FileName;

            // check whether the user clicked on OK and insert something nonempty and something else
            if (result != DialogResult.OK || newName.Length == 0 || newName == oldName)
                return;

            // set the appropriate action and new name to the event arguments
            _arguments.Rename(newName);
            Close();
        }

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

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

        private void btnOverwriteOlder_Click(object sender, System.EventArgs e)
        {
            _arguments.Overwrite(OverwriteCondition.Older);
            _overwriteOlder = true;
            Close();
        }

        private void btnOverwriteDiffSize_Click(object sender, System.EventArgs e)
        {
            _arguments.Overwrite(OverwriteCondition.SizeDiffers);
            _overwriteDifferentSize = true;
            Close();
        }

        private void btnOverwriteDiffChecksum_Click(object sender, EventArgs e)
        {
            _arguments.Overwrite(OverwriteCondition.ChecksumDiffers);
            _overwriteDifferentChecksum = true;
            Close();
        }

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

        private void btnResume_Click(object sender, EventArgs e)
        {
            _arguments.Resume();
            Close();
        }

        
    }
}
