using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace VINlib
{
    public class VinInfo
    {
        public static bool CheckVIN(string vin)
        {
            //JHMCM56557C404453
            if (vin.Length < 17)
            {
                return false;
            }
            var regexItemVIN = new Regex("^[A-HJ-NPR-Z0-9]*$"); //Только определённые символы могут использоваться
            if (regexItemVIN.IsMatch(vin) == false) //abcdABCD19213IhOsQpP
            {
                return false;
            }
            var regexItemWMI = new Regex("^[A-HJ-NPR-Z9]$"); //3-ий символ буква или 9
            if (regexItemWMI.IsMatch(vin[2].ToString()) == false)
            {
                return false;
            }
            var regexItemVDS = new Regex("^[0-9X]$"); //9-ый символ 0-9 или X
            if (regexItemVDS.IsMatch(vin[8].ToString()) == false)
            {
                return false;
            }
            var regexItemVIS = new Regex("^[0-9]*$"); //Последние 4 знака - цифры
            if (regexItemVIS.IsMatch(vin.Substring(13, 4).ToString()) == false)
            {
                return false;
            }
            var vinDigitalEquivalent = new int[17];
            
            //Провекрка сходства контрольной суммы
            for (int i = 0; i < 17; i++)
            {
                if (regexItemVDS.IsMatch(vin[i].ToString()) == false)
                {
                    switch (vin[i])
                    {
                        case 'A':
                            vinDigitalEquivalent[i] = 1; 
                            break;
                        case 'B':
                            vinDigitalEquivalent[i] = 2;
                            break;
                        case 'C':
                            vinDigitalEquivalent[i] = 3;
                            break;
                        case 'D':
                            vinDigitalEquivalent[i] = 4;
                            break;
                        case 'E':
                            vinDigitalEquivalent[i] = 5;
                            break;
                        case 'F':
                            vinDigitalEquivalent[i] = 6;
                            break;
                        case 'G':
                            vinDigitalEquivalent[i] = 7;
                            break;
                        case 'H':
                            vinDigitalEquivalent[i] = 8;
                            break;
                        case 'J':
                            vinDigitalEquivalent[i] = 1;
                            break;
                        case 'K':
                            vinDigitalEquivalent[i] = 2;
                            break;
                        case 'L':
                            vinDigitalEquivalent[i] = 3;
                            break;
                        case 'M':
                            vinDigitalEquivalent[i] = 4;
                            break;
                        case 'N':
                            vinDigitalEquivalent[i] = 5;
                            break;
                        case 'P':
                            vinDigitalEquivalent[i] = 7;
                            break;
                        case 'R':
                            vinDigitalEquivalent[i] = 9;
                            break;
                        case 'S':
                            vinDigitalEquivalent[i] = 2;
                            break;
                        case 'T':
                            vinDigitalEquivalent[i] = 3;
                            break;
                        case 'U':
                            vinDigitalEquivalent[i] = 4;
                            break;
                        case 'V':
                            vinDigitalEquivalent[i] = 5;
                            break;
                        case 'W':
                            vinDigitalEquivalent[i] = 6;
                            break;
                        case 'X':
                            vinDigitalEquivalent[i] = 7;
                            break;
                        case 'Y':
                            vinDigitalEquivalent[i] = 8;
                            break;
                        case 'Z':
                            vinDigitalEquivalent[i] = 9;
                            break;
                    }
                }
                else
                {
                    vinDigitalEquivalent[i] = Convert.ToInt32(vin[i].ToString());
                }
            }
            int vinWeight 
                = vinDigitalEquivalent[0] * 8
                + vinDigitalEquivalent[1] * 7
                + vinDigitalEquivalent[2] * 6
                + vinDigitalEquivalent[3] * 5
                + vinDigitalEquivalent[4] * 4
                + vinDigitalEquivalent[5] * 3
                + vinDigitalEquivalent[6] * 2
                + vinDigitalEquivalent[7] * 10
                + vinDigitalEquivalent[9] * 9
                + vinDigitalEquivalent[10] * 8
                + vinDigitalEquivalent[11] * 7
                + vinDigitalEquivalent[12] * 6
                + vinDigitalEquivalent[13] * 5
                + vinDigitalEquivalent[14] * 4
                + vinDigitalEquivalent[15] * 3
                + vinDigitalEquivalent[16] * 2;
            int CNK = vinWeight / 11;
            int CNK1 = CNK * 11;
            int checkDigit = vinWeight - CNK1;
            if (checkDigit == 10)
            {
                if (vin[8] != 'X')
                {
                    return false;
                }
            }
            else
            {
                if (Convert.ToInt32(vin[8].ToString()) != checkDigit)
                {
                    return false;
                }
            }

            return true;
        }

        class Country
        {
            public Regex RegexCountry { get; set; }
            public string CountryName { get; set; }
        }
        public static string GetVINCountry(string vin)
        {
            var regexItemVIN = new Regex("^[A-HJ-NPR-Z0-9]*$"); //Только определённые символы могут использоваться
            if (regexItemVIN.IsMatch(vin) == false)
            {
                return "Не используется";
            }

            string сountryСode = vin.Substring(0, 2).ToString(); //Нужная часть vin

            var countryCodes = new Dictionary<int, Country> //Все шаблоны для стран
            {
                //Африка
                { 0, new Country { RegexCountry = new Regex("^A[A-H]$"), CountryName = "ЮАР" } },
                { 1, new Country { RegexCountry = new Regex("^A[J-N]$"), CountryName = "Котд’Ивуар" } },
                { 2, new Country { RegexCountry = new Regex("^A[P-Z0-9]$"), CountryName = "Не используется" } },
                { 3, new Country { RegexCountry = new Regex("^B[A-E]$"), CountryName = "Ангола" } },
                { 4, new Country { RegexCountry = new Regex("^B[F-K]$"), CountryName = "Кения" } },
                { 5, new Country { RegexCountry = new Regex("^B[L-R]$"), CountryName = "Танзания" } },
                { 6, new Country { RegexCountry = new Regex("^B[S-Z0-9]$"), CountryName = "Не используется" } },
                { 7, new Country { RegexCountry = new Regex("^C[A-E]$"), CountryName = "Бенин" } },
                { 8, new Country { RegexCountry = new Regex("^C[F-K]$"), CountryName = "Мадагаскар" } },
                { 9, new Country { RegexCountry = new Regex("^C[L-R]$"), CountryName = "Тунис" } },
                { 10, new Country { RegexCountry = new Regex("^C[S-Z0-9]$"), CountryName = "Не используется" } },
                { 11, new Country { RegexCountry = new Regex("^D[A-E]$"), CountryName = "Тунис" } },
                { 12, new Country { RegexCountry = new Regex("^D[F-K]$"), CountryName = "Марокко" } },
                { 13, new Country { RegexCountry = new Regex("^D[L-R]$"), CountryName = "Замбия" } },
                { 14, new Country { RegexCountry = new Regex("^D[S-Z0-9]$"), CountryName = "Не используется" } },
                { 15, new Country { RegexCountry = new Regex("^E[A-E]$"), CountryName = "Эфиопия" } },
                { 16, new Country { RegexCountry = new Regex("^E[F-K]$"), CountryName = "Мозамбик" } },
                { 17, new Country { RegexCountry = new Regex("^E[L-Z0-9]$"), CountryName = "Не используется" } },
                { 18, new Country { RegexCountry = new Regex("^F[A-E]$"), CountryName = "Гана" } },
                { 19, new Country { RegexCountry = new Regex("^F[F-K]$"), CountryName = "Нигерия" } },
                { 20, new Country { RegexCountry = new Regex("^F[L-Z0-9]$"), CountryName = "Не используется" } },
                { 21, new Country { RegexCountry = new Regex("^G[A-Z0-9]$"), CountryName = "Не используется" } },
                { 22, new Country { RegexCountry = new Regex("^H[A-Z0-9]$"), CountryName = "Не используется" } },

                //Азия
                { 23, new Country { RegexCountry = new Regex("^J[A-T]$"), CountryName = "Япония" } },
                { 24, new Country { RegexCountry = new Regex("^K[A-E]$"), CountryName = "Шри Ланка" } },
                { 25, new Country { RegexCountry = new Regex("^K[F-K]$"), CountryName = "Израиль" } },
                { 26, new Country { RegexCountry = new Regex("^K[L-R]$"), CountryName = "Южная Корея" } },
                { 27, new Country { RegexCountry = new Regex("^K[S-Z0-9]$"), CountryName = "Казахстан" } },
                { 28, new Country { RegexCountry = new Regex("^L[A-Z0-9]$"), CountryName = "Китай" } },
                { 29, new Country { RegexCountry = new Regex("^M[A-E]$"), CountryName = "Индия" } },
                { 30, new Country { RegexCountry = new Regex("^M[F-K]$"), CountryName = "Индонезия" } },
                { 31, new Country { RegexCountry = new Regex("^M[L-R]$"), CountryName = "Таиланд" } },
                { 32, new Country { RegexCountry = new Regex("^M[S-Z0-9]$"), CountryName = "Не используется" } },
                { 33, new Country { RegexCountry = new Regex("^N[F-K]$"), CountryName = "Пакистан" } },
                { 34, new Country { RegexCountry = new Regex("^N[L-R]$"), CountryName = "Турция" } },
                { 35, new Country { RegexCountry = new Regex("^N[T-Z0-9]$"), CountryName = "Не используется" } },
                { 36, new Country { RegexCountry = new Regex("^P[A-E]$"), CountryName = "Филиппины" } },
                { 37, new Country { RegexCountry = new Regex("^P[F-K]$"), CountryName = "Сингапур" } },
                { 38, new Country { RegexCountry = new Regex("^P[L-R]$"), CountryName = "Малайзия" } },
                { 39, new Country { RegexCountry = new Regex("^P[S-Z0-9]$"), CountryName = "Не используется" } },
                { 40, new Country { RegexCountry = new Regex("^R[A-E]$"), CountryName = "ОАЭ" } },
                { 41, new Country { RegexCountry = new Regex("^R[F-K]$"), CountryName = "Тайвань" } },
                { 42, new Country { RegexCountry = new Regex("^R[L-R]$"), CountryName = "Вьетнам" } },
                { 43, new Country { RegexCountry = new Regex("^R[S-Z0-9]$"), CountryName = "Саудовская Аравия" } },

                //Европа
                { 44, new Country { RegexCountry = new Regex("^S[A-M]$"), CountryName = "Великобритания" } },
                { 45, new Country { RegexCountry = new Regex("^S[N-T]$"), CountryName = "Германия" } },
                { 46, new Country { RegexCountry = new Regex("^S[U-Z]$"), CountryName = "Польша" } },
                { 47, new Country { RegexCountry = new Regex("^S[1-4]$"), CountryName = "Латвия" } },
                { 48, new Country { RegexCountry = new Regex("^T[A-H]$"), CountryName = "Швейцария" } },
                { 49, new Country { RegexCountry = new Regex("^T[J-P]$"), CountryName = "Чехия" } },
                { 50, new Country { RegexCountry = new Regex("^T[R-V]$"), CountryName = "Венгрия" } },
                { 51, new Country { RegexCountry = new Regex("^T[W-Z1]$"), CountryName = "Португалия" } },
                { 52, new Country { RegexCountry = new Regex("^T[2-90]$"), CountryName = "Не используется" } },
                { 53, new Country { RegexCountry = new Regex("^U[A-G]$"), CountryName = "Не используется" } },
                { 54, new Country { RegexCountry = new Regex("^U[H-M]$"), CountryName = "Дания" } },
                { 55, new Country { RegexCountry = new Regex("^U[N-T]$"), CountryName = "Ирландия" } },
                { 56, new Country { RegexCountry = new Regex("^U[U-Z]$"), CountryName = "Румыния" } },
                { 57, new Country { RegexCountry = new Regex("^U[1-4]$"), CountryName = "Не используется" } },
                { 58, new Country { RegexCountry = new Regex("^U[5-7]$"), CountryName = "Словакия" } },
                { 59, new Country { RegexCountry = new Regex("^U[8-90]$"), CountryName = "Не используется" } },
                { 60, new Country { RegexCountry = new Regex("^V[A-E]$"), CountryName = "Австрия" } },
                { 61, new Country { RegexCountry = new Regex("^V[F-R]$"), CountryName = "Франция" } },
                { 62, new Country { RegexCountry = new Regex("^V[S-W]$"), CountryName = "Испания" } },
                { 63, new Country { RegexCountry = new Regex("^V[X-Z1-2]$"), CountryName = "Сербия" } },
                { 64, new Country { RegexCountry = new Regex("^V[3-5]$"), CountryName = "Хорватия" } },
                { 65, new Country { RegexCountry = new Regex("^V[6-90]$"), CountryName = "Эстония" } },
                { 66, new Country { RegexCountry = new Regex("^W[A-Z0-9]$"), CountryName = "Германия" } },
                { 67, new Country { RegexCountry = new Regex("^X[A-E]$"), CountryName = "Болгария" } },
                { 68, new Country { RegexCountry = new Regex("^X[F-K]$"), CountryName = "Греция" } },
                { 69, new Country { RegexCountry = new Regex("^X[L-R]$"), CountryName = "Нидерланды" } },
                { 70, new Country { RegexCountry = new Regex("^X[S-W]$"), CountryName = "СССР/СНГ" } },
                { 71, new Country { RegexCountry = new Regex("^X[X-Z1-2]$"), CountryName = "Люксембург" } },
                { 72, new Country { RegexCountry = new Regex("^X[3-90]$"), CountryName = "Россия" } },
                { 73, new Country { RegexCountry = new Regex("^Y[A-E]$"), CountryName = "Бельгия" } },
                { 74, new Country { RegexCountry = new Regex("^Y[F-K]$"), CountryName = "Финляндия" } },
                { 75, new Country { RegexCountry = new Regex("^Y[L-R]$"), CountryName = "Мальта" } },
                { 76, new Country { RegexCountry = new Regex("^Y[S-W]$"), CountryName = "Швеция" } },
                { 77, new Country { RegexCountry = new Regex("^Y[X-Z1-2]$"), CountryName = "Норвегия" } },
                { 78, new Country { RegexCountry = new Regex("^Y[3-5]$"), CountryName = "Беларусь" } },
                { 79, new Country { RegexCountry = new Regex("^Y[6-90]$"), CountryName = "Украина" } },
                { 80, new Country { RegexCountry = new Regex("^Z[A-R]$"), CountryName = "Италия" } },
                { 81, new Country { RegexCountry = new Regex("^Z[S-W]$"), CountryName = "Не используется" } },
                { 82, new Country { RegexCountry = new Regex("^Z[X-Z1-2]$"), CountryName = "Словения" } },
                { 83, new Country { RegexCountry = new Regex("^Z[3-5]$"), CountryName = "Литва" } },
                { 84, new Country { RegexCountry = new Regex("^Z[6-90]$"), CountryName = "Россия" } },

                //Северная Америка
                { 85, new Country { RegexCountry = new Regex("^1[A-Z0-9]$"), CountryName = "США" } },
                { 86, new Country { RegexCountry = new Regex("^2[A-Z0-9]$"), CountryName = "Канада" } },
                { 87, new Country { RegexCountry = new Regex("^3[A-W]$"), CountryName = "Мексика" } },
                { 88, new Country { RegexCountry = new Regex("^3[X-Z1-7]$"), CountryName = "Коста Рика" } },
                { 89, new Country { RegexCountry = new Regex("^3[8-90]$"), CountryName = "Каймановы острова" } },
                { 90, new Country { RegexCountry = new Regex("^4[A-Z0-9]$"), CountryName = "США" } },
                { 91, new Country { RegexCountry = new Regex("^5[A-Z0-9]$"), CountryName = "США" } },

                //Океания
                { 92, new Country { RegexCountry = new Regex("^6[A-W]$"), CountryName = "Австралия" } },
                { 93, new Country { RegexCountry = new Regex("^6[X-Z0-9]$"), CountryName = "Не используется" } },
                { 94, new Country { RegexCountry = new Regex("^7[A-E]$"), CountryName = "Новая Зеландия" } },
                { 95, new Country { RegexCountry = new Regex("^7[F-Z0-9]$"), CountryName = "Не используется" } },

                //Южная Америка
                { 96, new Country { RegexCountry = new Regex("^8[A-E]$"), CountryName = "Аргентина" } },
                { 97, new Country { RegexCountry = new Regex("^8[F-K]$"), CountryName = "Чили" } },
                { 98, new Country { RegexCountry = new Regex("^8[L-R]$"), CountryName = "Эквадор" } },
                { 99, new Country { RegexCountry = new Regex("^8[S-W]$"), CountryName = "Перу" } },
                { 100, new Country { RegexCountry = new Regex("^8[X-Z1-2]$"), CountryName = "Венесуэла" } },
                { 101, new Country { RegexCountry = new Regex("^8[2-90]$"), CountryName = "Не используется" } },
                { 102, new Country { RegexCountry = new Regex("^9[A-E]$"), CountryName = "Бразилия" } },
                { 103, new Country { RegexCountry = new Regex("^9[F-K]$"), CountryName = "Колумбия" } },
                { 104, new Country { RegexCountry = new Regex("^9[L-R]$"), CountryName = "Парагвай" } },
                { 105, new Country { RegexCountry = new Regex("^9[S-W]$"), CountryName = "Уругвай" } },
                { 106, new Country { RegexCountry = new Regex("^9[X-Z1-2]$"), CountryName = "Тринидад и Тобаго" } },
                { 107, new Country { RegexCountry = new Regex("^9[3-9]$"), CountryName = "Бразилия" } },
                { 108, new Country { RegexCountry = new Regex("^90$"), CountryName = "Не используется" } },
            };

            var regexAfrica = new Regex("^[A-H]$");
            var regexAsia = new Regex("^[J-R]$");
            var regexEurope = new Regex("^[S-Z]$");
            var regexNorthAmerica = new Regex("^[1-5]$");
            var regexOceania = new Regex("^[6-7]$");
            var regexSouthAmerica = new Regex("^[8-9]$");

            if (regexAfrica.IsMatch(vin[0].ToString())) //Проверка континента Африка
            {
                for (int i = 0; i <= 22; i++) 
                {
                    countryCodes.TryGetValue(i, out Country _currentCountry);
                    if (_currentCountry.RegexCountry.IsMatch(сountryСode))
                    {
                        return _currentCountry.CountryName;
                    }
                }
            }
            if (regexAsia.IsMatch(vin[0].ToString())) //Проверка континента Азия
            {
                for (int i = 23; i <= 43; i++)
                {
                    countryCodes.TryGetValue(i, out Country _currentCountry);
                    if (_currentCountry.RegexCountry.IsMatch(сountryСode))
                    {
                        return _currentCountry.CountryName;
                    }
                }
            }
            if (regexEurope.IsMatch(vin[0].ToString())) //Проверка континента Европа
            {
                for (int i = 44; i <= 84; i++)
                {
                    countryCodes.TryGetValue(i, out Country _currentCountry);
                    if (_currentCountry.RegexCountry.IsMatch(сountryСode))
                    {
                        return _currentCountry.CountryName;
                    }
                }
            }
            if (regexNorthAmerica.IsMatch(vin[0].ToString())) //Проверка континента Северная Америка
            {
                for (int i = 85; i <= 91; i++)
                {
                    countryCodes.TryGetValue(i, out Country _currentCountry);
                    if (_currentCountry.RegexCountry.IsMatch(сountryСode))
                    {
                        return _currentCountry.CountryName;
                    }
                }
            }
            if (regexOceania.IsMatch(vin[0].ToString())) //Проверка континента Океания
            {
                for (int i = 92; i <= 95; i++)
                {
                    countryCodes.TryGetValue(i, out Country _currentCountry);
                    if (_currentCountry.RegexCountry.IsMatch(сountryСode))
                    {
                        return _currentCountry.CountryName;
                    }
                }
            }
            if (regexSouthAmerica.IsMatch(vin[0].ToString())) //Проверка континента Южная Америка
            {
                for (int i = 96; i <= 108; i++)
                {
                    countryCodes.TryGetValue(i, out Country _currentCountry);
                    if (_currentCountry.RegexCountry.IsMatch(сountryСode))
                    {
                        return _currentCountry.CountryName;
                    }
                }
            }

            return "Не используется";
        }

        public static int GetTransportYear(string vin)
        {
            var vinYearMapping = new Dictionary<char, int>
            {
                {'S', 1995}, {'T', 1996}, {'V', 1997}, {'W', 1998}, {'X', 1999},
                {'Y', 2000}, {'1', 2001}, {'2', 2002}, {'3', 2003}, {'4', 2004},
                {'5', 2005}, {'6', 2006}, {'7', 2007}, {'8', 2008}, {'9', 2009},
                {'A', 2010}, {'B', 2011}, {'C', 2012}, {'D', 2013}, {'E', 2014},
                {'F', 2015}, {'G', 2016}, {'H', 2017}, {'J', 2018}, {'K', 2019},
                {'L', 2020}, {'M', 2021}, {'N', 2022}, {'P', 2023}, {'R', 2024},
            };

            vinYearMapping.TryGetValue(vin[9], out int dateCar);
            
            return dateCar;
        }
    }
}
