//  
//   Rebex Sample Code License
// 
//   Copyright 2026, 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.Windows.Forms;
using System.Threading.Tasks;
using Rebex.Net;
using System.Drawing;

namespace Rebex.Samples
{
    public class MainForm : System.Windows.Forms.Form
    {
        private const string Title = "WinForm Sample HTTP Downloader";

        // Rebex WebClient instance
        private Rebex.Net.WebClient _client;

        // required by the Windows Form Designer
        private System.ComponentModel.IContainer components = null;

        private System.Windows.Forms.Label Label1;
        private System.Windows.Forms.Label Label4;
        private System.Windows.Forms.SaveFileDialog dlgSaveFile;
        private System.Windows.Forms.Button cmdGet;
        private System.Windows.Forms.TextBox txtUrl;
        private System.Windows.Forms.ProgressBar pbProgress;
        private System.Windows.Forms.Button cmdAbort;
        private System.Windows.Forms.StatusStrip statusStrip;
        private System.Windows.Forms.ToolStripStatusLabel statusLabel;
        private System.Windows.Forms.CheckBox cbAcceptAll;

        /// <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.txtUrl = new System.Windows.Forms.TextBox();
            this.Label1 = new System.Windows.Forms.Label();
            this.cmdGet = new System.Windows.Forms.Button();
            this.Label4 = new System.Windows.Forms.Label();
            this.pbProgress = new System.Windows.Forms.ProgressBar();
            this.dlgSaveFile = new System.Windows.Forms.SaveFileDialog();
            this.cmdAbort = new System.Windows.Forms.Button();
            this.statusStrip = new System.Windows.Forms.StatusStrip();
            this.statusLabel = new System.Windows.Forms.ToolStripStatusLabel();
            this.cbAcceptAll = new System.Windows.Forms.CheckBox();
            this.statusStrip.SuspendLayout();
            this.SuspendLayout();
            // 
            // txtUrl
            // 
            this.txtUrl.Location = new System.Drawing.Point(40, 8);
            this.txtUrl.Name = "txtUrl";
            this.txtUrl.Size = new System.Drawing.Size(336, 20);
            this.txtUrl.TabIndex = 0;
            this.txtUrl.Text = "https://test.rebex.net/content/rebex-logo.gif";
            // 
            // Label1
            // 
            this.Label1.Location = new System.Drawing.Point(8, 8);
            this.Label1.Name = "Label1";
            this.Label1.Size = new System.Drawing.Size(32, 20);
            this.Label1.TabIndex = 1;
            this.Label1.Text = "URL:";
            this.Label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
            // 
            // cmdGet
            // 
            this.cmdGet.Location = new System.Drawing.Point(376, 8);
            this.cmdGet.Name = "cmdGet";
            this.cmdGet.Size = new System.Drawing.Size(80, 20);
            this.cmdGet.TabIndex = 2;
            this.cmdGet.Text = "Get";
            this.cmdGet.Click += new System.EventHandler(this.cmdGet_Click);
            // 
            // Label4
            // 
            this.Label4.Location = new System.Drawing.Point(40, 32);
            this.Label4.Name = "Label4";
            this.Label4.Size = new System.Drawing.Size(336, 45);
            this.Label4.TabIndex = 7;
            this.Label4.Text = "This sample demonstrates using asynchronous methods. It does not block the user i" +
    "nterface at all!";
            // 
            // pbProgress
            // 
            this.pbProgress.Location = new System.Drawing.Point(8, 112);
            this.pbProgress.Name = "pbProgress";
            this.pbProgress.Size = new System.Drawing.Size(448, 20);
            this.pbProgress.TabIndex = 8;
            // 
            // dlgSaveFile
            // 
            this.dlgSaveFile.FileName = "doc1";
            // 
            // cmdAbort
            // 
            this.cmdAbort.Enabled = false;
            this.cmdAbort.Location = new System.Drawing.Point(376, 32);
            this.cmdAbort.Name = "cmdAbort";
            this.cmdAbort.Size = new System.Drawing.Size(80, 20);
            this.cmdAbort.TabIndex = 9;
            this.cmdAbort.Text = "Abort";
            this.cmdAbort.Click += new System.EventHandler(this.cmdAbort_Click);
            // 
            // statusStrip
            // 
            this.statusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.statusLabel});
            this.statusStrip.Location = new System.Drawing.Point(0, 135);
            this.statusStrip.Name = "statusStrip";
            this.statusStrip.Size = new System.Drawing.Size(464, 22);
            this.statusStrip.SizingGrip = false;
            this.statusStrip.TabIndex = 10;
            // 
            // statusLabel
            // 
            this.statusLabel.Name = "statusLabel";
            this.statusLabel.Size = new System.Drawing.Size(39, 17);
            this.statusLabel.Text = "Ready";
            // 
            // cbAcceptAll
            // 
            this.cbAcceptAll.Location = new System.Drawing.Point(40, 80);
            this.cbAcceptAll.Name = "cbAcceptAll";
            this.cbAcceptAll.Size = new System.Drawing.Size(336, 32);
            this.cbAcceptAll.TabIndex = 14;
            this.cbAcceptAll.Text = "Do not validate any server certificates - this is insecure but useful for testing" +
    ".";
            // 
            // MainForm
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(464, 157);
            this.Controls.Add(this.cbAcceptAll);
            this.Controls.Add(this.statusStrip);
            this.Controls.Add(this.cmdAbort);
            this.Controls.Add(this.pbProgress);
            this.Controls.Add(this.Label4);
            this.Controls.Add(this.cmdGet);
            this.Controls.Add(this.Label1);
            this.Controls.Add(this.txtUrl);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
            this.MaximizeBox = false;
            this.Name = "MainForm";
            this.Text = "WinForm Sample HTTP Downloader";
            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_Closing);
            this.statusStrip.ResumeLayout(false);
            this.statusStrip.PerformLayout();
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private async void cmdGet_Click(object sender, System.EventArgs e)
        {
            // validate URL and get the path
            Uri url;
            try
            {
                url = new Uri(txtUrl.Text);
            }
            catch (Exception err)
            {
                ShowMessage(err);
                return;
            }

            if (!url.Scheme.Equals("https") && !url.Scheme.Equals("http"))
            {
                MessageBox.Show("URL must be an HTTPS or HTTP URL.", Title, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            string fileName;
            if (url.AbsolutePath.EndsWith("/"))
            {
                fileName = "index.html";
            }
            else
            {
                fileName = System.IO.Path.GetFileName(url.AbsolutePath);
            }

            // display File Save dialog and let user select destination
            dlgSaveFile.FileName = fileName;
            dlgSaveFile.Filter = "All files (*.*)|*.*";
            if (dlgSaveFile.ShowDialog() != DialogResult.OK)
            {
                return;
            }

            try
            {
                cmdGet.Enabled = false;

                // create an instance of WebClient class
                _client = new Rebex.Net.WebClient();

                _client.DownloadProgressChanged += new EventHandler<WebClientProgressChangedEventArgs>(http_TransferProgressChanged);

                cmdAbort.Enabled = true;
                statusLabel.Text = "Connecting...";

                _client.Settings.SslAcceptAllCertificates = cbAcceptAll.Checked;

                // Download the file
                statusLabel.Text = "Downloading...";
                await _client.DownloadFileAsync(url, dlgSaveFile.FileName);

                MessageBox.Show("Transfer is finished.", Title, MessageBoxButtons.OK, MessageBoxIcon.Information);
                statusLabel.Text = "Disconnecting...";
            }
            catch (Exception err)
            {
                // if an error occured, display the message
                ShowMessage(err);
            }
            finally
            {
                // clean up at the end
                CleanUp();
            }
        }

        private void CleanUp()
        {
            // dispose the WebClient object
            if (_client != null)
            {
                _client.Dispose();
                _client = null;
            }

            // set the window title back to the original title
            Text = Title;

            // reset the progress bar
            pbProgress.Value = 0;

            // reset the status bar
            statusLabel.Text = "Ready";

            // disable Abort button
            cmdAbort.Enabled = false;

            // enable Get button
            cmdGet.Enabled = true;
        }

        private void ShowMessage(Exception err)
        {
            var aggregateEx = err as AggregateException;
            if (aggregateEx != null)
            {
                foreach (Exception ex in aggregateEx.InnerExceptions)
                {
                    ShowMessage(ex);
                }
                return;
            }

            MessageBox.Show(err.Message, Title, MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        private void Abort()
        {
            // The client object may have been set to nothing while we were waiting
            // for user's response in MainForm_Closing callback. It might be being
            // set to nothing even at this moment by another thread. By using our
            // own temporary object (which cannot be set nothing by other threads),
            // we are able to make this method thread-safe.
            // Also please note that even though the WebClient object itself might have
            // been disconnected and disposed, it is still safe to call the Abort
            // method - it will do nothing if no asynchronous operation is taking
            // place. This allows us to avoid using synchronization classes
            // such as Monitor or Mutex and still being thread-safe.
            var tmp = _client;
            if (tmp != null)
            {
                tmp.Cancel();
                statusLabel.Text = "Aborting...";
                cmdAbort.Enabled = false;
            }
        }

        private void cmdAbort_Click(System.Object sender, System.EventArgs e)
        {
            Abort();
        }

        private void MainForm_Closing(object sender, System.Windows.Forms.FormClosingEventArgs e)
        {
            // if the form is closing and transfer is in progress, ask the user what to do
            if (_client != null)
            {
                DialogResult res = MessageBox.Show("Transfer is in progress, do you want to abort it?", Title, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning);
                if (res != DialogResult.Yes)
                {
                    e.Cancel = true;
                }
                else
                {
                    Abort();
                }
            }
        }

        private void http_TransferProgressChanged(object sender, WebClientProgressChangedEventArgs e)
        {
            this.Invoke((MethodInvoker)delegate {
                if (e.ProgressPercentage <= pbProgress.Maximum && e.ProgressPercentage > pbProgress.Minimum)
                {
                    // gets called if there is a progress in transfer, so update our display accordingly
                    pbProgress.Value = e.ProgressPercentage;
                    Text = String.Format("{0} bytes transferred.", e.BytesTransferred);
                }
            });
        }

        public MainForm()
        {
            Application.EnableVisualStyles();
            CheckForIllegalCrossThreadCalls = true;

            InitializeComponent();

            // load app icon
            using (var stream = GetType().Assembly.GetManifestResourceStream("Rebex.Samples.Icon.ico"))
            {
                this.Icon = new Icon(stream);
            }
        }

        [STAThread]
        static void Main()
        {
            // set the trial license key
            Rebex.Licensing.Key = Rebex.Samples.TrialKey.Key;


            Application.EnableVisualStyles();
            Application.Run(new MainForm());
        }
    }
}