﻿// ==========================================================================
//  Squidex Headless CMS
// ==========================================================================
//  Copyright (c) Squidex UG (haftungsbeschränkt)
//  All rights reserved. Licensed under the MIT license.
// ==========================================================================

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;

namespace GenerateLanguages
{
    public static class Program
    {
        public static void Main()
        {
            var languageCodesFile = new FileInfo("../../../../../src/Squidex.Infrastructure/language-codes.csv");
            var languageFile = Path.Combine(languageCodesFile.DirectoryName, "Languages.cs");

            var writer = new StringWriter();
            writer.WriteLine("// ==========================================================================");
            writer.WriteLine("//  Languages.cs");
            writer.WriteLine("//  Squidex Headless CMS");
            writer.WriteLine("// ==========================================================================");
            writer.WriteLine("//  Copyright (c) Squidex UG (haftungsbeschränkt)");
            writer.WriteLine("//  All rights reserved. Licensed under the MIT license.");
            writer.WriteLine("// ==========================================================================");
            writer.WriteLine("// <autogenerated/>");
            writer.WriteLine();
            writer.WriteLine("using System.CodeDom.Compiler;");
            writer.WriteLine();
            writer.WriteLine("namespace Squidex.Infrastructure");
            writer.WriteLine("{");
            writer.WriteLine("    [GeneratedCode(\"LanguagesGenerator\", \"1.0\")]");
            writer.WriteLine("    partial class Language");
            writer.WriteLine("    {");

            var languages = GetLanguages(languageCodesFile).ToList();

            foreach (var language in languages)
            {
                var fieldName = language.Iso2Code.ToUpperInvariant();

                writer.WriteLine($"        public static readonly Language {fieldName} = AddLanguage(\"{language.Iso2Code}\", \"{language.EnglishName}\");");
            }

            writer.WriteLine();

            foreach (var culture in GetCultures(languages))
            {
                var fieldName = culture.EnglishName.ToFieldName();

                writer.WriteLine($"        public static readonly Language {fieldName} = AddLanguage(\"{culture.Code}\", \"{culture.EnglishName}\");");
            }

            writer.WriteLine("    }");
            writer.WriteLine("}");

            File.WriteAllText(languageFile, writer.ToString());
        }

        private static string ToFieldName(this string name)
        {
            var sb = new StringBuilder();

            foreach (var c in name)
            {
                if (char.IsLetterOrDigit(c))
                {
                    sb.Append(c);
                }
            }

            return sb.ToString();
        }

        private static IEnumerable<(string Code, string EnglishName)> GetCultures(List<(string Iso2Code, string EnglishName)> languages)
        {
            return CultureInfo.GetCultures(CultureTypes.SpecificCultures)
                .Where(x => x.ToString().Length == 5)
                .Where(x => languages.Any(l => l.Iso2Code.Equals(x.TwoLetterISOLanguageName, StringComparison.OrdinalIgnoreCase)))
                .GroupBy(x => x.TwoLetterISOLanguageName)
                .Where(x => x.Count() > 1)
                .SelectMany(x => x)
                .Select(x => (x.ToString(), x.EnglishName));
        }

        private static IEnumerable<(string Iso2Code, string EnglishName)> GetLanguages(FileInfo file)
        {
            var uniqueCodes = new HashSet<string>(new[] { "iv" });

            var resourceStream = file.OpenRead();

            using (var reader = new StreamReader(resourceStream, Encoding.UTF8))
            {
                reader.ReadLine();

                while (!reader.EndOfStream)
                {
                    var line = reader.ReadLine();

                    var iso2Code = line.Substring(1, 2);

                    if (uniqueCodes.Add(iso2Code))
                    {
                        yield return (iso2Code, line.Substring(6, line.Length - 7));
                    }
                    else
                    {
                        Console.WriteLine("Languages contains duplicate {0}", iso2Code);
                    }
                }
            }
        }
    }
}
