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

namespace Rebex.Samples
{
    /// <summary>
    /// Summary description for Form1.
    /// </summary>
    public class FileListEvents : System.Windows.Forms.Form
    {
        private System.Windows.Forms.Label lblServerDirectory;
        private System.Windows.Forms.ListView listServer;
        private System.Windows.Forms.ColumnHeader name;
        private System.Windows.Forms.ColumnHeader size;
        private System.Windows.Forms.ColumnHeader date;
        private System.Windows.Forms.Button btnConnect;
        private System.Windows.Forms.Button btnRefresh;
        private StatusStrip statusStrip;
        private ToolStripStatusLabel statusLabel;

        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.Container components = null;

        // ftp object
        private Ftp _ftp;

        private int _itemCounter;

        public FileListEvents()
        {
            Application.EnableVisualStyles();
            CheckForIllegalCrossThreadCalls = true;
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();

            //
            // TODO: Add any constructor code after InitializeComponent call
            //
            _itemCounter = 0;
            btnRefresh.Enabled = false;
        }

        /// <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.lblServerDirectory = new System.Windows.Forms.Label();
            this.listServer = new System.Windows.Forms.ListView();
            this.name = new System.Windows.Forms.ColumnHeader();
            this.size = new System.Windows.Forms.ColumnHeader();
            this.date = new System.Windows.Forms.ColumnHeader();
            this.btnConnect = new System.Windows.Forms.Button();
            this.btnRefresh = new System.Windows.Forms.Button();
            this.statusStrip = new System.Windows.Forms.StatusStrip();
            this.statusLabel = new System.Windows.Forms.ToolStripStatusLabel();
            this.statusStrip.SuspendLayout();
            this.SuspendLayout();
            // 
            // lblServerDirectory
            // 
            this.lblServerDirectory.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
                | System.Windows.Forms.AnchorStyles.Right)));
            this.lblServerDirectory.BackColor = System.Drawing.SystemColors.InactiveCaption;
            this.lblServerDirectory.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
            this.lblServerDirectory.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
            this.lblServerDirectory.ForeColor = System.Drawing.SystemColors.InactiveCaptionText;
            this.lblServerDirectory.Location = new System.Drawing.Point(8, 8);
            this.lblServerDirectory.Name = "lblServerDirectory";
            this.lblServerDirectory.Size = new System.Drawing.Size(336, 16);
            this.lblServerDirectory.TabIndex = 2;
            this.lblServerDirectory.Text = "/root";
            this.lblServerDirectory.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
            // 
            // listServer
            // 
            this.listServer.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
                | System.Windows.Forms.AnchorStyles.Left) 
                | System.Windows.Forms.AnchorStyles.Right)));
            this.listServer.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
                                                                                         this.name,
                                                                                         this.size,
                                                                                         this.date});
            this.listServer.FullRowSelect = true;
            this.listServer.Location = new System.Drawing.Point(8, 24);
            this.listServer.MultiSelect = false;
            this.listServer.Name = "listServer";
            this.listServer.Size = new System.Drawing.Size(336, 328);
            this.listServer.TabIndex = 3;
            this.listServer.View = System.Windows.Forms.View.Details;
            this.listServer.DoubleClick += new System.EventHandler(this.listServer_DoubleClick);
            // 
            // name
            // 
            this.name.Text = "Name";
            this.name.Width = 150;
            // 
            // size
            // 
            this.size.Text = "Size";
            this.size.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
            // 
            // date
            // 
            this.date.Text = "Date";
            this.date.Width = 120;
            // 
            // btnConnect
            // 
            this.btnConnect.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
            this.btnConnect.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.btnConnect.Location = new System.Drawing.Point(272, 360);
            this.btnConnect.Name = "btnConnect";
            this.btnConnect.TabIndex = 4;
            this.btnConnect.Text = "&Connect...";
            this.btnConnect.Click += new System.EventHandler(this.btnConnect_Click);
            // 
            // btnRefresh
            // 
            this.btnRefresh.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
            this.btnRefresh.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.btnRefresh.Location = new System.Drawing.Point(8, 360);
            this.btnRefresh.Name = "btnRefresh";
            this.btnRefresh.TabIndex = 5;
            this.btnRefresh.Text = "&Refresh";
            this.btnRefresh.Click += new System.EventHandler(this.btnRefresh_Click);
            // 
            // statusStrip
            // 
            this.statusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.statusLabel});
            this.statusStrip.Location = new System.Drawing.Point(0, 392);
            this.statusStrip.Name = "statusStrip";
            this.statusStrip.Size = new System.Drawing.Size(352, 22);
            this.statusStrip.TabIndex = 6;
            // 
            // statusLabel
            // 
            this.statusLabel.Name = "statusLabel";
            this.statusLabel.Size = new System.Drawing.Size(90, 21);
            // 
            // FileListEvents
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(352, 414);
            this.Controls.Add(this.statusStrip);
            this.Controls.Add(this.btnRefresh);
            this.Controls.Add(this.btnConnect);
            this.Controls.Add(this.listServer);
            this.Controls.Add(this.lblServerDirectory);
            this.Name = "FileListEvents";
            this.Text = "FileListEvents";
            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FileListEvents_Closing);
            this.statusStrip.ResumeLayout(false);
            this.statusStrip.PerformLayout();
            this.ResumeLayout(false);
            this.PerformLayout();

        }
        #endregion

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static void Main() 
        {
            // set the trial license key
            Rebex.Licensing.Key = Rebex.Samples.TrialKey.Key;


            Application.Run(new FileListEvents());
        }

        private void btnConnect_Click(object sender, System.EventArgs e)
        {
            if (_ftp != null) 
            {
                btnRefresh.Enabled = false;
                _ftp.Disconnect();
                _ftp = null;
                MakeFtpList();
                btnConnect.Text = "Connect...";
                return;
            }

            Connection con = new Connection();
            if (con.ShowDialog() == DialogResult.OK) 
            {
                try 
                {
                    statusLabel.Text = "Connecting...";

                    _ftp = new Ftp();

                    _ftp.ListItemReceived += Ftp_ListItemReceived;

                    // Connect to the server.
                    _ftp.Connect(con.Hostname, con.Port);

                    // If TLS/SSL was checked, try to secure the connection.
                    if (con.Secure)
                    {
                        _ftp.Settings.SslAcceptAllCertificates = con.AcceptAll;
                        _ftp.Secure();
                    }

                    // Log in.
                    _ftp.Login(con.Username, con.Password);

                    btnConnect.Text = "Disconnect";

                    MakeFtpList();

                    btnRefresh.Enabled = true;
                } 
                catch (Exception x)
                {
                    if (_ftp != null) 
                    {
                        _ftp.Disconnect();
                        _ftp = null;
                    }

                    MessageBox.Show(x.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        private void Ftp_ListItemReceived(object sender, FtpListItemReceivedEventArgs e)
        {
            // We just recieved a list item from server. Let's play with it a little bit :)

            string[] pars;
            // Detects if the item represents directory or file.
            // (We do this, because we want to display different information
            // for files and different information for directories.)
            if (e.Item.IsDirectory)
                pars = new string[] { e.Item.Name, "", e.Item.LastWriteTime.ToString() };
            else
                pars = new string[] {	e.Item.Name,
                                        e.Item.Length.ToString(),
                                        e.Item.LastWriteTime.ToString()
                                    };

            // Create a ListViewItem from gathered info.
            ListViewItem lvi = new ListViewItem(pars);
            lvi.Tag = e.Item;

            // Add ListViewItem to our ListView (which represents the remote file system for us).
            listServer.Items.Add(lvi);

            // It's not guaranteed that the server has to return the list of files/dirs in a sorted form, 
            // so to avoid confusing the user we will sort out our ListView each time the list item
            // arrives to keep it nicely sorted and tidy ;)
            listServer.ListViewItemSorter = new ListViewColumnSorter();
            listServer.Sort();

            // Make sure that our changes to the ListView are visible to the user.
            listServer.Update();

            // Update our counter of items (=dirs/files) in our list.
            _itemCounter++;
            statusLabel.Text = string.Format("Loaded {0} item(s).", _itemCounter);
        }

        private void MakeFtpList() 
        {
            listServer.Items.Clear();

            // Not connected?
            if (_ftp == null) 
            {
                lblServerDirectory.Text = "/root";
                return;
            }

            listServer.Items.Add("..");

            lblServerDirectory.Text = _ftp.GetCurrentDirectory();
            _ftp.GetList();
        }

        private void listServer_DoubleClick(object sender, System.EventArgs e)
        {
            try 
            {
                // Not connected?
                if (_ftp == null) 
                    return;

                if (listServer.Items.Count < 1)
                    return;

                if (listServer.SelectedItems.Count < 1)
                    listServer.Items[0].Selected = true;

                ListViewItem item = listServer.SelectedItems[0];

                // Is the selected item a directory?
                if (item.SubItems.Count > 1) 
                {
                    if (item.SubItems[1].Text != "")
                        return;
                }

                _ftp.ChangeDirectory(item.Text);

                _itemCounter = 0;
                statusLabel.Text = "No items.";
                MakeFtpList();
            } 
            catch (FtpException x) 
            {
                if (x.Status == FtpExceptionStatus.Timeout ||
                    x.Status == FtpExceptionStatus.ConnectFailure ||
                    x.Status == FtpExceptionStatus.ConnectionClosed)
                    btnConnect_Click(sender, e);

                MessageBox.Show(x.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void FileListEvents_Closing(object sender, System.Windows.Forms.FormClosingEventArgs e)
        {
            if (_ftp != null)
                _ftp.Dispose();
        }

        private void btnRefresh_Click(object sender, System.EventArgs e)
        {
            try 
            {
                _itemCounter = 0;
                statusLabel.Text = "Refreshing...";
                MakeFtpList();
            } 
            catch (FtpException x) 
            {
                if (x.Status == FtpExceptionStatus.Timeout)
                    btnConnect_Click(sender, e);

                MessageBox.Show(x.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
    }

    public class ListViewColumnSorter : MultiComparer, IComparer
    {
        public ListViewColumnSorter()
            : base(new FileSystemItemComparer(FileSystemItemComparerType.FileType, SortingOrder.Ascending), new FileSystemItemComparer(FileSystemItemComparerType.Name)) 
        {
        }

        int IComparer.Compare(object x, object y) 
        {
            ListViewItem listViewX = (ListViewItem)x;
            ListViewItem listViewY = (ListViewItem)y;

            FtpItem itemX = (FtpItem)listViewX.Tag;
            FtpItem itemY = (FtpItem)listViewY.Tag;

            if (itemX == null)
            {
                if (itemY == null)
                    return 0;

                return -1;
            }
            else if (itemY == null)
            {
                return 1;
            }

            return base.Compare(itemX, itemY);
        }
    }
}
