/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "hangul_p.h"

QT_BEGIN_NAMESPACE
namespace QtVirtualKeyboard {

const QList<ushort> Hangul::initials = QList<ushort>()
    << 0x3131 << 0x3132 << 0x3134 << 0x3137 << 0x3138 << 0x3139 << 0x3141
    << 0x3142 << 0x3143 << 0x3145 << 0x3146 << 0x3147 << 0x3148 << 0x3149
    << 0x314A << 0x314B << 0x314C << 0x314D << 0x314E;
const QList<ushort> Hangul::finals = QList<ushort>()
    << 0x0000 << 0x3131 << 0x3132 << 0x3133 << 0x3134 << 0x3135 << 0x3136
    << 0x3137 << 0x3139 << 0x313A << 0x313B << 0x313C << 0x313D << 0x313E
    << 0x313F << 0x3140 << 0x3141 << 0x3142 << 0x3144 << 0x3145 << 0x3146
    << 0x3147 << 0x3148 << 0x314A << 0x314B << 0x314C << 0x314D << 0x314E;
const QMap<ushort, Hangul::HangulMedialIndex> Hangul::doubleMedialMap =
    Hangul::initDoubleMedialMap();
const QMap<ushort, Hangul::HangulFinalIndex> Hangul::doubleFinalMap =
    Hangul::initDoubleFinalMap();
const int Hangul::SBase = 0xAC00;
const int Hangul::LBase = 0x1100;
const int Hangul::VBase = 0x314F;
const int Hangul::TBase = 0x11A7;
const int Hangul::LCount = 19;
const int Hangul::VCount = 21;
const int Hangul::TCount = 28;
const int Hangul::NCount = Hangul::VCount * Hangul::TCount; // 588
const int Hangul::SCount = Hangul::LCount * Hangul::NCount; // 11172

/*!
    \class QtVirtualKeyboard::Hangul
    \internal
*/

QString Hangul::decompose(const QString &source)
{
    QString result;
    const int len = source.length();
    for (int i = 0; i < len; i++) {
        QChar ch = source.at(i);
        int SIndex = (int)ch.unicode() - SBase;
        if (SIndex >= 0 && SIndex < SCount) {

            // Decompose initial consonant
            result.append(QChar((int)initials[SIndex / NCount]));

            // Decompose medial vowel and check if it consists of double Jamo
            int VIndex = (SIndex % NCount) / TCount;
            ushort key = findDoubleMedial((HangulMedialIndex)VIndex);
            if (key) {
                HangulMedialIndex VIndexA, VIndexB;
                unpackDoubleMedial(key, VIndexA, VIndexB);
                result.append(QChar(VBase + (int)VIndexA));
                result.append(QChar(VBase + (int)VIndexB));
            } else {
                result.append(QChar(VBase + VIndex));
            }

            // Decompose final consonant and check if it consists of double Jamo
            int TIndex = SIndex % TCount;
            if (TIndex != 0) {
                key = findDoubleFinal((HangulFinalIndex)TIndex);
                if (key) {
                    HangulFinalIndex TIndexA, TIndexB;
                    unpackDoubleFinal(key, TIndexA, TIndexB);
                    result.append(QChar(finals[(int)TIndexA]));
                    result.append(QChar(finals[(int)TIndexB]));
                } else {
                    result.append(QChar(finals[TIndex]));
                }
            }
        } else {
            result.append(ch);
        }
    }
    return result;
}

QString Hangul::compose(const QString &source)
{
    const int len = source.length();
    if (len == 0)
        return QString();

    // Always add the initial character into buffer.
    // The last character will serve as the current
    // Hangul Syllable.
    QChar last = source.at(0);
    QString result = QString(last);

    // Go through the input buffer starting at next character
    for (int i = 1; i < len; i++) {
        const QChar ch = source.at(i);

        // Check to see if the character is Hangul Compatibility Jamo
        const ushort unicode = ch.unicode();
        if (isJamo(unicode)) {

            // Check to see if the character is syllable
            const ushort lastUnicode = last.unicode();
            int SIndex = (int)lastUnicode - SBase;
            if (SIndex >= 0 && SIndex < SCount) {

                // Check to see if the syllable type is LV or LV+T
                int TIndex = SIndex % TCount;
                if (TIndex == 0) {

                    // If the current character is final consonant, then
                    // make syllable of form LV+T
                    TIndex = finals.indexOf(unicode);
                    if (TIndex != -1) {
                        last = QChar((int)lastUnicode + TIndex);
                        result.replace(result.length() - 1, 1, last);
                        continue;
                    }

                    // Check to see if the current character is vowel
                    HangulMedialIndex VIndexB = (HangulMedialIndex)((int)unicode - VBase);
                    if (isMedial(VIndexB)) {

                        // Some medial Jamos do not exist in the keyboard layout as is.
                        // Such Jamos can only be formed by combining the two specific Jamos,
                        // aka the double Jamos.

                        HangulMedialIndex VIndexA = (HangulMedialIndex)((SIndex % NCount) / TCount);
                        if (isMedial(VIndexA)) {

                            // Search the double medial map if such a combination exists
                            ushort key = packDoubleMedial(VIndexA, VIndexB);
                            const auto it = doubleMedialMap.constFind(key);
                            if (it != doubleMedialMap.cend()) {

                                // Update syllable by adding the difference between
                                // the vowels indices
                                HangulMedialIndex VIndexD = it.value();
                                int VDiff = (int)VIndexD - (int)VIndexA;
                                last = QChar((int)lastUnicode + VDiff * TCount);
                                result.replace(result.length() - 1, 1, last);
                                continue;
                            }
                        }
                    }

                } else {

                    // Check to see if current jamo is vowel
                    int VIndex = (int)unicode - VBase;
                    if (VIndex >= 0 && VIndex < VCount) {

                        // Since some initial and final consonants use the same
                        // Unicode values, we need to check whether the previous final
                        // Jamo is actually an initial Jamo of the next syllable.
                        //
                        // Consider the following scenario:
                        //      LVT+V == not possible
                        //      LV, L+V == possible
                        int LIndex = initials.indexOf(finals[TIndex]);
                        if (LIndex >= 0 && LIndex < LCount) {

                            // Remove the previous final jamo from the syllable,
                            // making the current syllable of form LV
                            last = QChar((int)lastUnicode - TIndex);
                            result.replace(result.length() - 1, 1, last);

                            // Make new syllable of form LV
                            last = QChar(SBase + (LIndex * VCount + VIndex) * TCount);
                            result.append(last);
                            continue;
                        }

                        // Check to see if the current final Jamo is double consonant.
                        // In this scenario, the double consonant is split into parts
                        // and the second part is removed from the current syllable.
                        // Then the second part is joined with the current vowel making
                        // the new syllable of form LV.
                        ushort key = findDoubleFinal((HangulFinalIndex)TIndex);
                        if (key) {

                            // Split the consonant into two jamos and remove the
                            // second jamo B from the current syllable
                            HangulFinalIndex TIndexA, TIndexB;
                            unpackDoubleFinal(key, TIndexA, TIndexB);
                            last = QChar((int)lastUnicode - TIndex + (int)TIndexA);
                            result.replace(result.length() - 1, 1, last);

                            // Add new syllable by combining the initial jamo
                            // and the current vowel
                            LIndex = initials.indexOf(finals[TIndexB]);
                            last = QChar(SBase + (LIndex * VCount + VIndex) * TCount);
                            result.append(last);
                            continue;
                        }
                    }

                    // Check whether the current consonant can connect to current
                    // consonant forming a double final consonant
                    HangulFinalIndex TIndexA = (HangulFinalIndex)TIndex;
                    if (isFinal(TIndexA)) {

                        HangulFinalIndex TIndexB = (HangulFinalIndex)finals.indexOf(unicode);
                        if (isFinal(TIndexB)) {

                            // Search the double final map if such a combination exists
                            ushort key = packDoubleFinal(TIndexA, TIndexB);
                            const auto it = doubleFinalMap.constFind(key);
                            if (it != doubleFinalMap.cend()) {

                                // Update syllable by adding the difference between
                                // the consonant indices
                                HangulFinalIndex TIndexD = it.value();
                                int TDiff = (int)TIndexD - (int)TIndexA;
                                last = QChar((int)lastUnicode + TDiff);
                                result.replace(result.length() - 1, 1, last);
                                continue;
                            }
                        }
                    }
                }

            } else {

                // The last character is not syllable.
                // Check to see if the last character is an initial consonant
                int LIndex = initials.indexOf(lastUnicode);
                if (LIndex != -1) {

                    // If the current character is medial vowel,
                    // make syllable of form LV
                    int VIndex = (int)unicode - VBase;
                    if (VIndex >= 0 && VIndex < VCount) {
                        last = QChar(SBase + (LIndex * VCount + VIndex) * TCount);
                        result.replace(result.length() - 1, 1, last);
                        continue;
                    }
                }

            }
        }

        // Otherwise, add the character into buffer
        last = ch;
        result = result.append(ch);
    }
    return result;
}

bool Hangul::isJamo(const ushort &unicode)
{
    return unicode >= 0x3131 && unicode <= 0x3163;
}

bool Hangul::isMedial(HangulMedialIndex vowel)
{
    return vowel >= HANGUL_MEDIAL_A && vowel <= HANGUL_MEDIAL_I;
}

bool Hangul::isFinal(HangulFinalIndex consonant)
{
    return consonant >= HANGUL_FINAL_KIYEOK && consonant <= HANGUL_FINAL_HIEUH;
}

ushort Hangul::findDoubleMedial(HangulMedialIndex vowel)
{
    return doubleMedialMap.key(vowel, 0);
}

ushort Hangul::findDoubleFinal(HangulFinalIndex consonant)
{
    return doubleFinalMap.key(consonant, 0);
}

// Packs two Hangul Jamo indices into 16-bit integer.
// The result can be used as a key to the double jamos lookup table.
// Note: The returned value is not a Unicode character!
ushort Hangul::packDoubleMedial(HangulMedialIndex a, HangulMedialIndex b)
{
    Q_ASSERT(isMedial(a));
    Q_ASSERT(isMedial(b));
    return (ushort)a | ((ushort)b << 8);
}

ushort Hangul::packDoubleFinal(HangulFinalIndex a, HangulFinalIndex b)
{
    Q_ASSERT(isFinal(a));
    Q_ASSERT(isFinal(b));
    return (ushort)a | ((ushort)b << 8);
}

void Hangul::unpackDoubleMedial(ushort key, HangulMedialIndex &a, HangulMedialIndex &b)
{
    a = (HangulMedialIndex)(key & 0xFF);
    b = (HangulMedialIndex)(key >> 8);
    Q_ASSERT(isMedial(a));
    Q_ASSERT(isMedial(b));
}

void Hangul::unpackDoubleFinal(ushort key, HangulFinalIndex &a, HangulFinalIndex &b)
{
    a = (HangulFinalIndex)(key & 0xFF);
    b = (HangulFinalIndex)(key >> 8);
    Q_ASSERT(isFinal(a));
    Q_ASSERT(isFinal(b));
}

QMap<ushort, Hangul::HangulMedialIndex> Hangul::initDoubleMedialMap()
{
    QMap<ushort, HangulMedialIndex> map;
    map.insert(packDoubleMedial(HANGUL_MEDIAL_O, HANGUL_MEDIAL_A), HANGUL_MEDIAL_WA);
    map.insert(packDoubleMedial(HANGUL_MEDIAL_O, HANGUL_MEDIAL_AE), HANGUL_MEDIAL_WAE);
    map.insert(packDoubleMedial(HANGUL_MEDIAL_O, HANGUL_MEDIAL_I), HANGUL_MEDIAL_OE);
    map.insert(packDoubleMedial(HANGUL_MEDIAL_U, HANGUL_MEDIAL_EO), HANGUL_MEDIAL_WEO);
    map.insert(packDoubleMedial(HANGUL_MEDIAL_U, HANGUL_MEDIAL_E), HANGUL_MEDIAL_WE);
    map.insert(packDoubleMedial(HANGUL_MEDIAL_U, HANGUL_MEDIAL_I), HANGUL_MEDIAL_WI);
    map.insert(packDoubleMedial(HANGUL_MEDIAL_EU, HANGUL_MEDIAL_I), HANGUL_MEDIAL_YI);
    return map;
}

QMap<ushort, Hangul::HangulFinalIndex> Hangul::initDoubleFinalMap()
{
    QMap<ushort, HangulFinalIndex> map;
    map.insert(packDoubleFinal(HANGUL_FINAL_KIYEOK, HANGUL_FINAL_SIOS), HANGUL_FINAL_KIYEOK_SIOS);
    map.insert(packDoubleFinal(HANGUL_FINAL_NIEUN, HANGUL_FINAL_CIEUC), HANGUL_FINAL_NIEUN_CIEUC);
    map.insert(packDoubleFinal(HANGUL_FINAL_NIEUN, HANGUL_FINAL_HIEUH), HANGUL_FINAL_NIEUN_HIEUH);
    map.insert(packDoubleFinal(HANGUL_FINAL_RIEUL, HANGUL_FINAL_KIYEOK), HANGUL_FINAL_RIEUL_KIYEOK);
    map.insert(packDoubleFinal(HANGUL_FINAL_RIEUL, HANGUL_FINAL_MIEUM), HANGUL_FINAL_RIEUL_MIEUM);
    map.insert(packDoubleFinal(HANGUL_FINAL_RIEUL, HANGUL_FINAL_PIEUP), HANGUL_FINAL_RIEUL_PIEUP);
    map.insert(packDoubleFinal(HANGUL_FINAL_RIEUL, HANGUL_FINAL_SIOS), HANGUL_FINAL_RIEUL_SIOS);
    map.insert(packDoubleFinal(HANGUL_FINAL_RIEUL, HANGUL_FINAL_THIEUTH), HANGUL_FINAL_RIEUL_THIEUTH);
    map.insert(packDoubleFinal(HANGUL_FINAL_RIEUL, HANGUL_FINAL_PHIEUPH), HANGUL_FINAL_RIEUL_PHIEUPH);
    map.insert(packDoubleFinal(HANGUL_FINAL_RIEUL, HANGUL_FINAL_HIEUH), HANGUL_FINAL_RIEUL_HIEUH);
    map.insert(packDoubleFinal(HANGUL_FINAL_PIEUP, HANGUL_FINAL_SIOS), HANGUL_FINAL_PIEUP_SIOS);
    map.insert(packDoubleFinal(HANGUL_FINAL_SIOS, HANGUL_FINAL_SIOS), HANGUL_FINAL_SSANGSIOS);
    return map;
}

} // namespace QtVirtualKeyboard
QT_END_NAMESPACE
