using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Reflection;

namespace I18N
{
    public static class Catalog
    {
        public static bool Init(string locale_dir)
        {
            try
            {
                string lang = Environment.GetEnvironmentVariable("LANG");
                if (String.IsNullOrEmpty(lang) == false)
                {
                    lang = lang.Split('_', ' ', '-')[0].ToLower();

                    switch(lang)
                    {
                        case "de":
                        case "en":
                            break;

                        default:
                            lang = "en";
                            break;

                    }                    
                }
                else
                {
                    lang = CultureInfo.CurrentCulture.ToString().Split('-', '_')[0].ToLower();
                }

                 List<string> resources = new List<string>(Assembly.GetExecutingAssembly().GetManifestResourceNames());

                string resource_name = String.Format("ApoIdentStartSettings.i18n.{0}.po", lang);
                if (resources.Contains(resource_name) == false)
                    resource_name = String.Format("ApoIdentStartSettings.i18n.{0}.po", "en");

                

                Catalog.ReadMesssages(resource_name);
                Catalog.Locale = lang;
            }
            catch (Exception)
            {
                return false;
            }

            return true;
        }
        public static string GetString(string msgid)
        {
            if (Catalog.Messages.ContainsKey(msgid) == false)
                return msgid;

            return Catalog.Messages[msgid];
        }

        private static void ReadMesssages(string resource_name)
        {
            using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resource_name))
            {
                using (StreamReader sr = new StreamReader(stream, System.Text.Encoding.UTF8))
                {
                    bool is_reading_key = false;
                    bool is_reading_value = false;
                    bool is_fuzzy = false;
                    string key = String.Empty;
                    string value = String.Empty;

                    string line = null;
                    int ignore_lines = 0;
                    while ((line = sr.ReadLine()) != null)
                    {
                        if (ignore_lines < 2)
                        {
                            ignore_lines++;
                            continue;
                        }

                        line = line.Trim(' ');

                        if (String.IsNullOrEmpty(line) == true)                                                                                       
                        {
                            if (is_fuzzy == true)
                            {
                                is_fuzzy = false;
                                continue;
                            }

                            if (is_reading_value)
                            {
                                is_reading_value = false;
                                if (String.IsNullOrEmpty(key) == true)
                                {
                                    if (Catalog.Messages.ContainsKey(String.Empty) == false)
                                        Catalog.Messages.Add(String.Empty, String.Empty);

                                    continue;
                                }

                                if (String.IsNullOrEmpty(value) == false)
                                {
                                    Catalog.Messages.Add(Catalog.CorrectEscapeSequenzes(key), 
                                        Catalog.CorrectEscapeSequenzes(value));
                                }
                                   

                                continue;
                            }                           
                        }

                        if (line.StartsWith("#, fuzzy") == true)
                        {
                            is_fuzzy = true;
                        }

                        if (line.StartsWith("#") == true)
                            continue;

                        if (line.StartsWith("msgid") == true && is_fuzzy == false)
                        {
                            is_reading_key = true;
                            string tmp = line.Split(new string[] { "msgid" }, StringSplitOptions.None)[1].Trim(' ');
                            key = tmp.Substring(1, tmp.Length - 2);
                            continue;
                        }

                        if (line.StartsWith("msgstr") == true && is_fuzzy == false)
                        {
                            is_reading_key = false;
                            is_reading_value = true;
                            string tmp = line.Split(new string[] { "msgstr" }, StringSplitOptions.None)[1].Trim(' ');
                            value = tmp.Substring(1, tmp.Length - 2);
                            continue;
                        }

                        if (is_reading_key)
                        {
                            key += line.Substring(1, line.Length - 2);
                            continue;
                        }

                        if (is_reading_value)
                        {
                            value += line.Substring(1, line.Length - 2);
                            continue;
                        }
                    }
                }
            }
        }

        private static string CorrectEscapeSequenzes(string value)
        {
            string result = String.Empty;
            for (int i = 0; i < value.Length; i++)
            {
                if (value[i] == '\\')
                {
                    result += Catalog.GetEscapeSequence(value[i + 1]);
                    i++;
                }
                else
                {
                    result += value[i].ToString();
                }
            }

            return result;
        }

        private static string GetEscapeSequence(char c)
        {
            switch(c)
            {
                case 'a':
                    return "\a";

                case 'b':
                    return "\b";

                case 'f':
                    return "\f";

                case 'n':
                    return "\n";

                case 'r':
                    return "\r";

                case 't':
                    return "\t";

                case 'v':
                    return "\v";

                case '\'':
                    return "\'";

                case '\"':
                    return "\"";

                case '\\':
                    return "\\";

                default:
                    throw new ArgumentException(String.Format("Unknown escape sequence \\{0}", c));

            }
        }

        public static string Locale { get; private set; } = "en";
        private static Dictionary<string, string> Messages { get; set; } = new Dictionary<string, string>();
    }
}
