using System;
using System.IO;
using System.Runtime.Remoting.Messaging;
using System.Windows.Forms;
using File = System.IO.File;

namespace FileExpander
{
    public partial class FileExpanderForm : Form
    {
        private const int Kilobyte = 1024;
        private const int Megabyte = Kilobyte * 1024;
        private const int Gigabyte = Megabyte * 1024;

        public FileExpanderForm() => InitializeComponent();

        private void SelectButton_Click(object sender, EventArgs e)
        {
            using var dlg = new OpenFileDialog { Title = "Select file to expand", CheckFileExists = true };
            if (dlg.ShowDialog() != DialogResult.OK) return;
            FileValueLabel.Text = dlg.FileName;
            UpdateDisplay();
        }

        private void FileValueLabel_DragEnter(object sender, DragEventArgs e)
        {
            e.Effect =
                e.Data.GetDataPresent(DataFormats.FileDrop) && e.Data.GetData(DataFormats.FileDrop) is string[] arr && arr.Length == 1 && File.Exists(arr[0])
                    ? DragDropEffects.Link
                    : DragDropEffects.None;
        }

        private void FileValueLabel_DragDrop(object sender, DragEventArgs e)
        {
            FileValueLabel.Text = ((string[])e.Data.GetData(DataFormats.FileDrop))[0];
            UpdateDisplay();
        }

        private void UnitRadioButton_CheckedChanged(object sender, EventArgs e)
        {
            var self = (RadioButton)sender;
            if (self.Checked == false) return;
            UpdateDisplay();
        }

        private void GoButton_Click(object sender, EventArgs e)
        {
            using var fs = new FileStream(FileValueLabel.Text, FileMode.Open, FileAccess.Write, FileShare.None);
            fs.SetLength(fs.Length + GetExpand());
            fs.Close();
            MessageBox.Show("Success");
            Close();
        }

        //---------------------------

        private void UpdateDisplay()
        {
            var file = FileValueLabel.Text;
            if (!File.Exists(file))
            {
                SizeValueLabel.Text = "⚠ No such file";
                AfterExpandValueLabel.Text = "";
                return;
            }

            long size;
            try
            {
                //get real file size
                using var fs = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                size = fs.Length;
                fs.Close();
            }
            catch (Exception e)
            {
                SizeValueLabel.Text = "⚠ Failure to get file size:" + e.Message;
                AfterExpandValueLabel.Text = "";
                return;
            }

            SizeValueLabel.Text = HumanReadableSize(size) + $" ( {size:N0} bytes )";

            var expand = GetExpand();

            if (expand == -1)
            {
                AfterExpandValueLabel.Text = "- No Unit Selected -";
            }
            else
            {
                var final = size + expand;
                AfterExpandValueLabel.Text = HumanReadableSize(final) + $" ( {final:N0} bytes )";
            }
        }

        private long GetExpand()
        {
            long expand = -1;

            if (KbRadioButton.Checked) expand = (long)ExpandNumericUpDown.Value * Kilobyte;
            else if (MbRadioButton.Checked) expand = (long)ExpandNumericUpDown.Value * Megabyte;
            else if (GbRadioButton.Checked) expand = (long)ExpandNumericUpDown.Value * Gigabyte;

            return expand;
        }

        private static string HumanReadableSize(long size)
        {
            var sizes = new[] { "B", "KB", "MB", "GB", "TB" };
            double len = size;
            var order = 0;
            while (len >= 1024 && order < sizes.Length - 1)
            {
                order++;
                len /= 1024;
            }

            // Adjust the format string to your preferences. For example "{0:0.#}{1}" would
            // show a single decimal place, and no space.
            var result = String.Format("{0:0.##} {1}", len, sizes[order]);
            return result;
        }


    }
}