/* Any copyright is dedicated to the Public Domain.
 * https://creativecommons.org/publicdomain/zero/1.0/ */

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Tld {
    CentralWindows,
    Cyrillic,
    Western,
    Greek,
    TurkishAzeri,
    Hebrew,
    Arabic,
    Baltic,
    Vietnamese,
    Thai,
    Simplified,
    Traditional,
    Japanese,
    Korean,
    SimplifiedTraditional,
    TraditionalSimplified,
    CentralIso,
    IcelandicFaroese,
    WesternCyrillic,
    CentralCyrillic,
    WesternArabic,
    Generic,
    Eu,
}

pub fn classify_tld(tld: &[u8]) -> Tld {
    if tld.len() == 2 {
        let key = [tld[0], tld[1]];
        if let Ok(i) = TWO_LETTER_KEYS.binary_search(&key) {
            TWO_LETTER_VALUES[i]
        } else {
            Tld::Western
        }
    } else if tld.len() == 3 {
        match tld {
            b"edu" | b"gov" | b"mil" => Tld::Western,
            _ => Tld::Generic,
        }
    } else if tld.starts_with(b"xn--") && tld.len() >= 8 {
        // It's unclear is including the IDNs here is a good idea.
        // Clearly, they are an anachronism relative to the era
        // of legacy encodings. The idea, consistent with previous
        // approach in Firefox is to address the case where one
        // of these TLDs is configured as an alternative name for
        // a server that also serves the same content from a
        // two-ASCII-letter TLD. This makes the detection result
        // the same either way even though otherwise this thing
        // does not make much sense.
        if let Ok(i) = PUNYCODE_KEYS.binary_search(&&tld[4..]) {
            PUNYCODE_VALUES[i]
        } else {
            Tld::Generic
        }
    } else {
        Tld::Generic
    }
}

static TWO_LETTER_VALUES: [Tld; 87] = [
    Tld::Generic,               // ac
    Tld::Arabic,                // ae
    Tld::Arabic,                // af
    Tld::Generic,               // ai
    Tld::WesternCyrillic,       // am
    Tld::TurkishAzeri,          // az
    Tld::CentralCyrillic,       // ba
    Tld::Cyrillic,              // bg
    Tld::Arabic,                // bh
    Tld::Cyrillic,              // by
    Tld::Generic,               // bz
    Tld::Generic,               // cb
    Tld::Generic,               // cc
    Tld::Generic,               // cd
    Tld::Simplified,            // cn
    Tld::Generic,               // cx
    Tld::Greek,                 // cy
    Tld::CentralWindows,        // cz
    Tld::Generic,               // dj
    Tld::Arabic,                // dz
    Tld::Arabic,                // eg
    Tld::Eu,                    // eu
    Tld::Generic,               // fm
    Tld::IcelandicFaroese,      // fo
    Tld::WesternCyrillic,       // ge
    Tld::Greek,                 // gr
    Tld::TraditionalSimplified, // hk
    Tld::CentralWindows,        // hr
    Tld::CentralIso,            // hu
    Tld::Hebrew,                // il
    Tld::Generic,               // in
    Tld::Arabic,                // iq
    Tld::Arabic,                // ir
    Tld::IcelandicFaroese,      // is
    Tld::Arabic,                // jo
    Tld::Japanese,              // jp
    Tld::Cyrillic,              // kg
    Tld::Korean,                // kp
    Tld::Korean,                // kr
    Tld::Arabic,                // kw
    Tld::Cyrillic,              // kz
    Tld::Generic,               // la
    Tld::Arabic,                // lb
    Tld::Baltic,                // lt
    Tld::Baltic,                // lv
    Tld::Arabic,                // ly
    Tld::Arabic,                // ma
    Tld::Cyrillic,              // md
    Tld::Generic,               // me
    Tld::Cyrillic,              // mk
    Tld::Cyrillic,              // mn
    Tld::TraditionalSimplified, // mo
    Tld::Arabic,                // mr
    Tld::Generic,               // ms
    Tld::WesternArabic,         // my
    Tld::Generic,               // nu
    Tld::Arabic,                // om
    Tld::Arabic,                // pk
    Tld::CentralIso,            // pl
    Tld::Arabic,                // ps
    Tld::Arabic,                // qa
    Tld::CentralWindows,        // ro
    Tld::Cyrillic,              // rs
    Tld::Cyrillic,              // ru
    Tld::Arabic,                // sa
    Tld::Arabic,                // sd
    Tld::SimplifiedTraditional, // sg
    Tld::CentralIso,            // si
    Tld::CentralWindows,        // sk
    Tld::Generic,               // st
    Tld::Cyrillic,              // su
    Tld::Arabic,                // sy
    Tld::Thai,                  // th
    Tld::Cyrillic,              // tj
    Tld::Generic,               // tk
    Tld::Cyrillic,              // tm
    Tld::Arabic,                // tn
    Tld::Generic,               // to
    Tld::TurkishAzeri,          // tr
    Tld::Generic,               // tv
    Tld::Traditional,           // tw
    Tld::Cyrillic,              // ua
    Tld::Cyrillic,              // uz
    Tld::Generic,               // vc
    Tld::Vietnamese,            // vn
    Tld::Generic,               // vu
    Tld::Arabic,                // ye
];

static TWO_LETTER_KEYS: [[u8; 2]; 87] = [
    [b'a', b'c'], // Generic
    [b'a', b'e'], // Arabic
    [b'a', b'f'], // Arabic
    [b'a', b'i'], // Generic
    [b'a', b'm'], // WesternCyrillic
    [b'a', b'z'], // TurkishAzeri
    [b'b', b'a'], // CentralCyrillic
    [b'b', b'g'], // Cyrillic
    [b'b', b'h'], // Arabic
    [b'b', b'y'], // Cyrillic
    [b'b', b'z'], // Generic
    [b'c', b'b'], // Generic
    [b'c', b'c'], // Generic
    [b'c', b'd'], // Generic
    [b'c', b'n'], // Simplified
    [b'c', b'x'], // Generic
    [b'c', b'y'], // Greek
    [b'c', b'z'], // CentralWindows
    [b'd', b'j'], // Generic
    [b'd', b'z'], // Arabic
    [b'e', b'g'], // Arabic
    [b'e', b'u'], // Eu
    [b'f', b'm'], // Generic
    [b'f', b'o'], // IcelandicFaroese
    [b'g', b'e'], // WesternCyrillic
    [b'g', b'r'], // Greek
    [b'h', b'k'], // TraditionalSimplified
    [b'h', b'r'], // CentralWindows
    [b'h', b'u'], // CentralIso
    [b'i', b'l'], // Hebrew
    [b'i', b'n'], // Generic
    [b'i', b'q'], // Arabic
    [b'i', b'r'], // Arabic
    [b'i', b's'], // IcelandicFaroese
    [b'j', b'o'], // Arabic
    [b'j', b'p'], // Japanese
    [b'k', b'g'], // Cyrillic
    [b'k', b'p'], // Korean
    [b'k', b'r'], // Korean
    [b'k', b'w'], // Arabic
    [b'k', b'z'], // Cyrillic
    [b'l', b'a'], // Generic
    [b'l', b'b'], // Arabic
    [b'l', b't'], // Baltic
    [b'l', b'v'], // Baltic
    [b'l', b'y'], // Arabic
    [b'm', b'a'], // Arabic
    [b'm', b'd'], // Cyrillic
    [b'm', b'e'], // Generic
    [b'm', b'k'], // Cyrillic
    [b'm', b'n'], // Cyrillic
    [b'm', b'o'], // TraditionalSimplified
    [b'm', b'r'], // Arabic
    [b'm', b's'], // Generic
    [b'm', b'y'], // WesternArabic
    [b'n', b'u'], // Generic
    [b'o', b'm'], // Arabic
    [b'p', b'k'], // Arabic
    [b'p', b'l'], // CentralIso
    [b'p', b's'], // Arabic
    [b'q', b'a'], // Arabic
    [b'r', b'o'], // CentralWindows
    [b'r', b's'], // Cyrillic
    [b'r', b'u'], // Cyrillic
    [b's', b'a'], // Arabic
    [b's', b'd'], // Arabic
    [b's', b'g'], // SimplifiedTraditional
    [b's', b'i'], // CentralIso
    [b's', b'k'], // CentralWindows
    [b's', b't'], // Generic
    [b's', b'u'], // Cyrillic
    [b's', b'y'], // Arabic
    [b't', b'h'], // Thai
    [b't', b'j'], // Cyrillic
    [b't', b'k'], // Generic
    [b't', b'm'], // Cyrillic
    [b't', b'n'], // Arabic
    [b't', b'o'], // Generic
    [b't', b'r'], // TurkishAzeri
    [b't', b'v'], // Generic
    [b't', b'w'], // Traditional
    [b'u', b'a'], // Cyrillic
    [b'u', b'z'], // Cyrillic
    [b'v', b'c'], // Generic
    [b'v', b'n'], // Vietnamese
    [b'v', b'u'], // Generic
    [b'y', b'e'], // Arabic
];

static PUNYCODE_KEYS: [&'static [u8]; 46] = [
    b"3e0b707e",           // Korean
    b"54b7fta0cc",         // Western
    b"80ao21a",            // Cyrillic
    b"90a3ac",             // Cyrillic
    b"90ae",               // Cyrillic
    b"90ais",              // Cyrillic
    b"clchc0ea0b2g2a9gcd", // SimplifiedTraditional
    b"d1alf",              // Cyrillic
    b"e1a4c",              // Eu
    b"fiqs8S",             // Simplified
    b"fiqz9S",             // Simplified
    b"fzc2c9e2c",          // Western
    b"j1amh",              // Cyrillic
    b"j6w193g",            // TraditionalSimplified
    b"kprw13d",            // Traditional
    b"kpry57d",            // Traditional
    b"l1acc",              // Cyrillic
    b"lgbbat1ad8j",        // Arabic
    b"mgb2ddes",           // Arabic
    b"mgb9awbf",           // Arabic
    b"mgba3a4f16a",        // Arabic
    b"mgbaam7a8h",         // Arabic
    b"mgbah1a3hjkrd",      // Arabic
    b"mgbai9azgqp6j",      // Arabic
    b"mgbayh7gpa",         // Arabic
    b"mgbc0a9azcg",        // Arabic
    b"mgbcpq6gpa1a",       // Arabic
    b"mgberp4a5d4ar",      // Arabic
    b"mgbpl2fh",           // Arabic
    b"mgbtx2b",            // Arabic
    b"mgbx4cd0ab",         // WesternArabic
    b"mix891f",            // TraditionalSimplified
    b"node",               // WesternCyrillic
    b"o3cw4h",             // Thai
    b"ogbpf8fl",           // Arabic
    b"p1ai",               // Cyrillic
    b"pgbs0dh",            // Arabic
    b"q7ce6a",             // Arabic
    b"qxa6a",              // Eu
    b"qxam",               // Greek
    b"wgbh1c",             // Arabic
    b"wgbl6a",             // Arabic
    b"xkc2al3hye2a",       // Western
    b"y9a3aq",             // WesternCyrillic
    b"yfro4i67o",          // SimplifiedTraditional
    b"ygbi2ammx",          // Arabic
];

static PUNYCODE_VALUES: [Tld; 46] = [
    Tld::Korean,                // 3e0b707e
    Tld::Western,               // 54b7fta0cc
    Tld::Cyrillic,              // 80ao21a
    Tld::Cyrillic,              // 90a3ac
    Tld::Cyrillic,              // 90ae
    Tld::Cyrillic,              // 90ais
    Tld::SimplifiedTraditional, // clchc0ea0b2g2a9gcd
    Tld::Cyrillic,              // d1alf
    Tld::Eu,                    // e1a4c
    Tld::Simplified,            // fiqs8S
    Tld::Simplified,            // fiqz9S
    Tld::Western,               // fzc2c9e2c
    Tld::Cyrillic,              // j1amh
    Tld::TraditionalSimplified, // j6w193g
    Tld::Traditional,           // kprw13d
    Tld::Traditional,           // kpry57d
    Tld::Cyrillic,              // l1acc
    Tld::Arabic,                // lgbbat1ad8j
    Tld::Arabic,                // mgb2ddes
    Tld::Arabic,                // mgb9awbf
    Tld::Arabic,                // mgba3a4f16a
    Tld::Arabic,                // mgbaam7a8h
    Tld::Arabic,                // mgbah1a3hjkrd
    Tld::Arabic,                // mgbai9azgqp6j
    Tld::Arabic,                // mgbayh7gpa
    Tld::Arabic,                // mgbc0a9azcg
    Tld::Arabic,                // mgbcpq6gpa1a
    Tld::Arabic,                // mgberp4a5d4ar
    Tld::Arabic,                // mgbpl2fh
    Tld::Arabic,                // mgbtx2b
    Tld::WesternArabic,         // mgbx4cd0ab
    Tld::TraditionalSimplified, // mix891f
    Tld::WesternCyrillic,       // node
    Tld::Thai,                  // o3cw4h
    Tld::Arabic,                // ogbpf8fl
    Tld::Cyrillic,              // p1ai
    Tld::Arabic,                // pgbs0dh
    Tld::Arabic,                // q7ce6a
    Tld::Eu,                    // qxa6a
    Tld::Greek,                 // qxam
    Tld::Arabic,                // wgbh1c
    Tld::Arabic,                // wgbl6a
    Tld::Western,               // xkc2al3hye2a
    Tld::WesternCyrillic,       // y9a3aq
    Tld::SimplifiedTraditional, // yfro4i67o
    Tld::Arabic,                // ygbi2ammx
];