using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using System.IO;
using System.Windows.Forms;
using static System.Console;
using static System.Threading.Thread;

namespace cce {
    class Transcoder {
        static internal string result = "";
        static private List<string> extended_dict = null;
        static private List<string> common_dict = null;
        static private Dictionary<char, char> substitution = new Dictionary<char, char>{
            {'a','a' },
            {'b','t' },
            {'c','y' },
            {'d','p' },
            {'e','e' },
            {'f','t' },
            {'g','j' },
            {'h','k' },
            {'i','i' },
            {'j','t' },
            {'k','k' },
            {'l','p' },
            {'m','s' },
            {'n','t' },
            {'o','o' },
            {'p','k' },
            {'q','r' },
            {'r','t' },
            {'s','y' },
            {'t','p' },
            {'u','u' },
            {'v','t' },
            {'w','j' },
            {'x','k' },
            {'y','y' },
            {'z','b' }
        };
        static private Dictionary<char, string> decode_key = new Dictionary<char, string>{
            {'a',"a" },
            {'t',"bfjnrv"},
            {'y',"csy" },
            {'p',"dlt" },
            {'e',"e" },
            {'j',"gw" },
            {'k',"hkpx" },
            {'i',"i" },
            {'s',"m" },
            {'o',"o" },
            {'r',"q" },
            {'u',"u" },
            {'b',"z" }

        };
        static internal void Teacher() {
            var pos = CursorTop;
            Write("Please enter the encrypted word: ");
            var cyphered = Console.ReadLine().ToLower();
            if (cyphered == "") return;
            CursorTop = pos;
            string translation = "";
            while (true) {
                Write($"Please enter a translation for \"{cyphered}\": ");
                translation = ReadLine().ToLower();
                if (raw_encode(cyphered).ToLower() == cyphered) {
                    Console.BackgroundColor = ConsoleColor.Green; Console.ForegroundColor = ConsoleColor.Black;
                    WriteLine("Cypher Match!"); ResetColor(); break;
                }
                Console.BackgroundColor = ConsoleColor.Red;
                WriteLine("Words don't match");
                ResetColor();
            }
            var entered = false;
            char cki;
            do {
                Utils.LagWrite(@"Where do you want to save the translation?
[1] Common words dictionary
[2] Extended words dictionary
>>> ".Replace("\r\n", "\n"));
                cki = ReadKey().KeyChar;
                WriteLine();
                if (extended_dict == null || common_dict == null) init();
                switch (cki) {
                    case '1':
                        if (common_dict.Contains(translation)) {
                            WriteLine("Error: Unable to add a new translation. Translation already present.");
                        } else common_dict.Add(translation);
                        entered = true;
                        break;
                    case '2':
                        if (extended_dict.Contains(translation)) {
                            WriteLine("Error: Unable to add a new translation. Translation already present.");
                        } else extended_dict.Add(translation);
                        entered = true;
                        break;
                    default:
                        CursorLeft--; WriteLine("Not a valid option");
                        break;
                }
            } while (!entered);
            Console.BackgroundColor = cki == '1' ? ConsoleColor.Green : ConsoleColor.Blue; Console.ForegroundColor = ConsoleColor.Black;
            WriteLine("Translation Added"); ResetColor();
            update();
        }
        static internal void Encode(string entry) {
            result = raw_encode(entry);
            WriteLine("Transcoding:\n{0}\n", entry);
            Utils.LagWrite(result);
        }
        static internal void Decode(string entry) {
            var sentence = entry.ToLower();
            //120x30, buffer 240x60
            if (sentence.Length >= 120) { BufferWidth = sentence.Length * 2; WindowWidth = sentence.Length + 20; }
            Clear();
            CursorVisible = false;
            var checker = init();
            if (!checker) {
                WriteLine("Unable to load dictionaries");
                return;
            }
            var cleaned = new char[sentence.Length];
            var symbols = new char[sentence.Length];
            var writeout = new char[sentence.Length];
            for (int i = 0; i < sentence.Length; i++) {
                if (sentence[i] >= 'a' && sentence[i] <= 'z') { cleaned[i] = sentence[i]; symbols[i] = 'x'; writeout[i] = '_'; } else { writeout[i] = symbols[i] = sentence[i]; cleaned[i] = ' '; }
            }
            var decode = string.Join("", cleaned).ToLower().Split(' ');
            //var decoded = new List<List<string>>();
            Console.BackgroundColor = ConsoleColor.Green;
            Console.Write("  "); ResetColor(); Console.WriteLine(" Frequent Words");
            Console.BackgroundColor = ConsoleColor.Blue;
            Console.Write("  "); ResetColor(); Console.WriteLine(" Infrequent Words");
            Console.BackgroundColor = ConsoleColor.Red;
            Console.Write("  "); ResetColor(); Console.WriteLine(" Letter decypher");
            WriteLine("Transcoding:\n{0}\n", entry);
            int memTop = CursorTop;
            int left = 0;
            Write(string.Join("", writeout));
            for (int i = 0; i < decode.Length; i++) {
                if (symbols[left] != 'x') left++;
                CursorTop = memTop;
                Console.BackgroundColor = ConsoleColor.Green;
                Console.ForegroundColor = ConsoleColor.Black;
                wordwrite(common_dict, decode[i], entry, left);
                Console.BackgroundColor = ConsoleColor.Blue;
                wordwrite(extended_dict, decode[i], entry, left);
                ResetColor();
                List<List<char>> letter_decode = new List<List<char>>();
                for (int j = 0; j < decode[i].Length; j++) {
                    if (decode_key.TryGetValue(decode[i][j], out string substituted)) {
                        var letterlist = new List<char>();
                        for (int h = 0; h < substituted.Length; h++) {
                            letterlist.Add(substituted[h]);
                        }
                        letter_decode.Add(letterlist);
                    } else {
                        letter_decode.Add(new List<char> { sentence[j] });
                    }
                }
                int top = CursorTop;
                int letterleft = left;
                Console.BackgroundColor = ConsoleColor.Red;
                Console.ForegroundColor = ConsoleColor.Black;
                for (int j = 0; j < letter_decode.Count; j++) {
                    for (int h = 0; h < letter_decode[j].Count; h++) {
                        CursorLeft = letterleft;
                        Write(Char.IsUpper(entry[CursorLeft]) ? Char.ToUpper(letter_decode[j][h]) : Char.ToLower(letter_decode[j][h]));
                        Sleep(10);
                        CursorTop++;
                    }
                    CursorTop = top;
                    letterleft++;
                }
                Sleep(80);
                left += decode[i].Length;
            }
            ResetColor();
            //return string.Join(" ", decoded);
        }
        static private void update() {
            uniquere();
            var dict = new Dictionary<string, List<string>>();
            File.WriteAllText(AppSettings.Dictionary, JsonConvert.SerializeObject(dict));
        }
        static private string raw_encode(string entry) {
            var sentence = entry.ToLower();
            char[] encoded = new char[entry.Length];
            for (int i = 0; i < sentence.Length; i++) {
                if (substitution.TryGetValue(sentence[i], out char substituted)) {
                    encoded[i] = Char.IsUpper(entry[i]) ? Char.ToUpper(substituted) : Char.ToLower(substituted);
                } else {
                    encoded[i] = entry[i];
                }
            }
            return String.Join("", encoded);
        }
        static internal bool init() {
            if (common_dict != null && extended_dict != null) return true;
            var checker = true;
            var dict = new Dictionary<string, List<string>>();
            WriteLine("[Loading Dictionary]");
            if (File.Exists(AppSettings.Dictionary)) dict = JsonConvert.DeserializeObject<Dictionary<string, List<string>>>(File.ReadAllText(AppSettings.Dictionary));
            else { WriteLine("File missing"); checker = false; }
            common_dict = dict["common"];
            extended_dict = dict["extended"];
            return checker;
        }
        static private void uniquere() {
            init();
            foreach (var item in common_dict) {
                if (extended_dict.Contains(item)) extended_dict.Remove(item);
            }
        }
        static private void wordwrite(List<string> collection, string decode, string entry,int left) {
            foreach (var item in collection) {
                var trans = raw_encode(item);
                if (trans == decode) {
                    CursorLeft = left;
                    //options.Add(item.Key);
                    for (int j = 0; j < item.Length; j++) {
                        Write(Char.IsUpper(entry[CursorLeft]) ? Char.ToUpper(item[j]) : Char.ToLower(item[j]));
                    }
                    Utils.VarSleep(10, low: 20,high:100);
                    CursorTop++;
                }
            }
        }
    }
}
