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

namespace SuperCryptEX
{
    public partial class GenerateKeyForm : Form
    {
        /* [#] ElGamal Key Details :
         * 
         * [A] Client :
         * Client - Public Key  = p, g, y, k    (For Encryption)
         * Client - Private Key = p, x, a       (For Decryption)
         * 
         * [B] Host :
         * Host - Private Key   = p, g, y, k    (For Encryption) -> Inverted, Basically Public Key
         * Host - Public Key    = p, x, a       (For Decryption) -> Inverted, Basically Private Key
         */

        private Class_General g = new Class_General();
        private Class_ElGamal eg = new Class_ElGamal();
        private bool nameLock = false;
        private string nameField = string.Empty;
        private string privateFolderPath = string.Empty;
        private string publicFolderPath = string.Empty;
        private enum KeyMode
        {
            Host = 0,
            Client,
        };
        private KeyMode km = KeyMode.Host;

        public GenerateKeyForm()
        {
            InitializeComponent();
        }

        // Function - Reset Fields
        private void genkey_resetFields()
        {
            text_genkey_name.Enabled = true;
            nameLock = false;

            nameField =
            privateFolderPath =
            publicFolderPath =
            text_genkey_name.Text =
            text_genkey_private_key.Text =
            text_genkey_public_key.Text =
                string.Empty;
        }

        // Function - Generate Keypair
        private string[] genkey_GenerateKeyPair()
        {
            string[] output = new string[2];

            // Inisialisasi Ulang Parameter agar Tidak Terjadi Crash
            eg.General_ClearVariables();

            // Buat Public Key dan Private Key Secara Acak
            eg.Go_GenerateRandomKey();

            // Cek Ulang Semua Parameter
            if (true == eg.General_CheckKeyValidity(eg.var_p, eg.var_x, eg.var_g, eg.var_y, eg.var_k, eg.var_a))
            {
                MessageBox.Show(
                    "=====================\n" +
                    "PARAMETER LIST\n" +
                    "=====================\n" +
                    "[A] Private Key : \n" +
                    "1. [p] = " + eg.var_p + "\n" +
                    "2. [x] = " + eg.var_x + "\n" +
                    "3. [a] = " + eg.var_a + "\n" +
                    "\n" +
                    "[B] Public Key : \n" +
                    "1. [p] = " + eg.var_p + "\n" +
                    "2. [g] = " + eg.var_g + "\n" +
                    "3. [y] = " + eg.var_y + "\n" +
                    "4. [k] = " + eg.var_k + "\n"
                    , "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);

                // Private Key
                output[0] = eg.var_p + "|" + eg.var_x + "|" + eg.var_a;

                // Public Key
                output[1] = eg.var_p + "|" + eg.var_g + "|" + eg.var_y + "|" + eg.var_k;
            }

            return output;
        }

        // Button - Confirm Name
        private void button_genkey_name_Click(object sender, EventArgs e)
        {
            if (text_genkey_name.Text != string.Empty)
            {
                bool isNameHasSpace = text_genkey_name.Text.Contains(" ");
                if (isNameHasSpace == false)
                {
                    nameLock = true;
                    text_genkey_name.Enabled = false;
                    nameField = text_genkey_name.Text;
                }
                else
                {
                    MessageBox.Show("Name Cannot Contain Whitespace!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
            }
            else
            {
                MessageBox.Show("Name Cannot Be Empty!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }

        }

        // Button - Save Private Key
        private void button_genkey_private_key_Click(object sender, EventArgs e)
        {
            if (nameLock == true)
            {
                FolderBrowserDialog savePrivateKeyBrowser = new FolderBrowserDialog();
                if (savePrivateKeyBrowser.ShowDialog() == DialogResult.OK)
                {
                    privateFolderPath = savePrivateKeyBrowser.SelectedPath;

                    if (km == KeyMode.Host)
                    {
                        privateFolderPath += "\\" + nameField + "_HostKey.mx_hpriv";
                        text_genkey_private_key.Text = privateFolderPath;
                    }
                    else
                    {
                        privateFolderPath += "\\" + nameField + "_ClientKey.mx_cpriv";
                        text_genkey_private_key.Text = privateFolderPath;
                    }

                    Console.WriteLine("Folder Path : " + privateFolderPath);
                }
            }
            else
            {
                MessageBox.Show("Please Confirm Your Name!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }

        // Button - Save Public Key
        private void button_genkey_public_key_Click(object sender, EventArgs e)
        {
            if (nameLock == true)
            {
                FolderBrowserDialog savePublicKeyBrowser = new FolderBrowserDialog();
                if (savePublicKeyBrowser.ShowDialog() == DialogResult.OK)
                {
                    publicFolderPath = savePublicKeyBrowser.SelectedPath;

                    if (km == KeyMode.Host)
                    {
                        publicFolderPath += "\\" + nameField + "_HostKey.mx_hpub";
                        text_genkey_public_key.Text = publicFolderPath;
                    }
                    else
                    {
                        publicFolderPath += "\\" + nameField + "_ClientKey.mx_cpub";
                        text_genkey_public_key.Text = publicFolderPath;
                    }

                    Console.WriteLine("Folder Path : " + publicFolderPath);
                }
            }
            else
            {
                MessageBox.Show("Please Confirm Your Name!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }

        // Button - Generate Key
        private void button_genkey_start_Click(object sender, EventArgs e)
        {
            if (privateFolderPath != string.Empty && publicFolderPath != string.Empty)
            {
                if (File.Exists(privateFolderPath) || File.Exists(publicFolderPath))
                {
                    // Ubah ke True Jika Ingin Rename
                    bool rename = false;

                    if (rename == true)
                    {
                        // Cek Apakah Nama File Private Key Sudah Ada atau Belum, Jika Sudah Ada -> Rename dengan Nama Baru
                        while (File.Exists(privateFolderPath))
                        {
                            privateFolderPath = g.renameIfNameAlreadyExists(privateFolderPath);
                        }

                        // Cek Apakah Nama File Public Key Sudah Ada atau Belum, Jika Sudah Ada -> Rename dengan Nama Baru
                        while (File.Exists(publicFolderPath))
                        {
                            publicFolderPath = g.renameIfNameAlreadyExists(publicFolderPath);
                        }
                    }
                    else
                    {
                        MessageBox.Show("File Already Exists, Please Choose Different Save Location!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    }
                }
                else
                {
                    // --- GENERATE KEY ---
                    string[] output = genkey_GenerateKeyPair();
                    byte[] privateByte;
                    byte[] publicByte;

                    // Konversi ke Byte
                    output[0] = Convert.ToBase64String(g.stringToByte(output[0]));
                    output[1] = Convert.ToBase64String(g.stringToByte(output[1]));

                    if (km == KeyMode.Host)
                    {

                        // Konversi ke Byte
                        privateByte = g.stringToByte(output[1]);
                        publicByte = g.stringToByte(output[0]);

                        Console.WriteLine("Host Private \t: " + g.byteToString(privateByte));
                        Console.WriteLine("Host Public \t: " + g.byteToString(publicByte));
                    }
                    else
                    {
                        // Konversi ke Byte
                        privateByte = Encoding.ASCII.GetBytes(output[0]);
                        publicByte = Encoding.ASCII.GetBytes(output[1]);

                        Console.WriteLine("Client Private \t: " + g.byteToString(privateByte));
                        Console.WriteLine("Client Public \t: " + g.byteToString(publicByte));
                    }



                    // Save Private Key ke Sebuah File
                    FileStream privateStream = new FileStream(privateFolderPath, FileMode.Create);
                    privateStream.Write(privateByte);
                    privateStream.Close();

                    // Save Public Key ke Sebuah File
                    FileStream publicStream = new FileStream(publicFolderPath, FileMode.Create);
                    publicStream.Write(publicByte);
                    publicStream.Close();
                }

            }
            else
            {
                MessageBox.Show("Choose Save Location for Both Private Key and Public Key!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }

        }

        // Radio - Host
        private void radio_genkey_host_CheckedChanged(object sender, EventArgs e)
        {
            km = KeyMode.Host;
            genkey_resetFields();
            group_genkey_generate_key.Text = "Generate Key - [HOST]";
        }

        // Radio - Client
        private void radio_genkey_client_CheckedChanged(object sender, EventArgs e)
        {
            km = KeyMode.Client;
            genkey_resetFields();
            group_genkey_generate_key.Text = "Generate Key - [CLIENT]";
        }

    }
}
