using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace KRY_0x00_netcore
{
    class do_a_crypto
    {
        private string usr_input_string;
        private string[] usr_input;
        private int alpha_usr_kee_a;
        private int beta_linear_shift;
        private int alphabet_length;

        public int GCD(int a, int b)
        {
            while (a != 0 && b != 0)
            {
                if (a > b)
                    a %= b;
                else
                    b %= a;
            }

            if (a == 0)
                return b;
            else
                return a;
        }
        protected string format_crypto_text(string crypto)
        {
            string crypto_formatted = "";
            int offset = 0;
            int todo = crypto.Length;

            while (todo != 0)
            {
                if (offset + 5 >= crypto.Length)
                {
                    for (int i = offset; i < crypto.Length; i++)
                    {
                        crypto_formatted += crypto.Substring(offset, 1);
                        todo--;
                        offset++;
                    }
                }
                else if (offset + 5 < crypto.Length)
                {
                    crypto_formatted += crypto.Substring(offset, 5);
                    todo -= 5;
                    offset += 5;
                    crypto_formatted += " ";
                }
            }
            return crypto_formatted;
        }


        public string encrypt(string user_input, char[] alphabet, int kee_a, int kee_b)
        {
            alphabet_length = alphabet.Length;

            alpha_usr_kee_a = kee_a;
            beta_linear_shift = kee_b;
            string crypto = "";
            usr_input_string = user_input;
            string[] usr_input = new string[usr_input_string.Length];
            bool doing_evil_stuff = true;

            if (GCD(alpha_usr_kee_a, alphabet_length) != 1)
            {
                MessageBox.Show("please pick another kee a, this one won't work", "do me a favour...", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return null;
            }

            Console.WriteLine("string[] usrinput ");
            for (int i = 0; i < usr_input_string.Length; i++)
            {
                usr_input[i] = usr_input_string.Substring(i, 1);
            }


            for (int i = 0; i < usr_input.Length; i++)
            {
                int q = 0;
                for (int m = 0; m < alphabet.Length; m++)
                {
                    if (usr_input[i] == Convert.ToString(alphabet[m]))
                    {
                        q = m;
                    }
                }
                int OxO = ((alpha_usr_kee_a * q) + beta_linear_shift) % alphabet_length;
                Console.Write(OxO);
                crypto += $"{alphabet[OxO]}";
            }
            Console.WriteLine();

            crypto = format_crypto_text(crypto);
            doing_evil_stuff = false; // :(
            return crypto;
        }

        public string decrypt(string user_input, char[] alphabet, int kee_a, int kee_b)
        {
            alphabet_length = alphabet.Length;

            alpha_usr_kee_a = kee_a;
            beta_linear_shift = kee_b;
            string plaintext = "";
            user_input = user_input.Replace(" ", string.Empty);
            string crypto = user_input;
            string[] usr_input = new string[crypto.Length];
            int inverse = mmi(alpha_usr_kee_a, alphabet_length);
            double dOxO;
            int OxO;


            if (inverse == 0)
            {
                MessageBox.Show("pick another kee a, this one sucks", "do me a favour or get BS...");
                return null;
            }
            else
            {
                /* do evil stuff */
                Console.WriteLine($"crypted data to decrypt: {crypto}");

                for (int i = 0; i < crypto.Length; i++)
                {
                    usr_input[i] = crypto.Substring(i, 1);
                }


                int q;

                for (int i = 0; i < usr_input.Length; i++)
                {
                    for (int m = 0; m < alphabet.Length; m++)
                    {
                        if (usr_input[i] == Convert.ToString(alphabet[m]))
                        {
                            q = m;
                            Console.WriteLine($"q: {q}, beta shift: {beta_linear_shift}, inverse: {inverse}, alphabet length: {alphabet_length}");

                            dOxO = ((q - beta_linear_shift) * inverse) % alphabet_length;
                            if (dOxO < 0)
                            {
                                dOxO = alphabet_length + dOxO;
                            }
                            OxO = Convert.ToInt32(dOxO);
                            plaintext += $"{alphabet[OxO]}";
                            break;
                        }
                    }
                }
                plaintext = format_crypto_text(plaintext);
                return plaintext;
            }
        }

        protected int mmi(int a, int alphlength)
        {
            int inverse;
            for (inverse = 0; inverse < alphlength; inverse++)
            {
                int darkmagic = (a * inverse) % alphlength;
                if (darkmagic == 1)
                {
                    return inverse;
                }
            }
            return 0;
        }
    }
}