/*
    This file is part of Kiten, a KDE Japanese Reference Tool
    SPDX-FileCopyrightText: 2001 Jason Katz-Brown <jason@katzbrown.com>
    SPDX-FileCopyrightText: 2006 Joseph Kerian <jkerian@gmail.com>

    SPDX-License-Identifier: LGPL-2.0-or-later
*/

#include "kromajiedit.h"

#include <KLocalizedString>
#include <KMessageBox>

#include <QAction>
#include <QActionGroup>
#include <QApplication>
#include <QFile>
#include <QKeyEvent>
#include <QMenu>
#include <QStandardPaths>
#include <QTextCodec>
#include <QTextStream>

KRomajiEdit::KRomajiEdit(QWidget *parent)
    : KLineEdit(parent) // KDE4 CHANGE
{
    m_kana = "unset";

    QString romkana = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kiten/romkana.cnv"));
    if (romkana.isNull()) {
        KMessageBox::error(nullptr, i18n("Romaji information file not installed, so Romaji conversion cannot be used."));
        return;
    }

    QFile f(romkana);

    if (!f.open(QIODevice::ReadOnly)) {
        KMessageBox::error(nullptr, i18n("Romaji information could not be loaded, so Romaji conversion cannot be used."));
    }

    QTextStream t(&f);
    t.setCodec(QTextCodec::codecForName("eucJP"));
    while (!t.atEnd()) // KDE4 CHANGE
    {
        QString s = t.readLine();

        QChar first = s.at(0);
        if (first == QLatin1Char('#')) // comment!
        {
            // nothing
        } else if (first == QLatin1Char('$')) // header
        {
            if (m_kana == "unset") {
                m_kana = "hiragana";
            } else {
                m_kana = "katakana";
            }
        } else // body
        {
            QStringList things(s.split(QLatin1Char(' ')));
            QString thekana(things.first());
            QString romaji(/* KDE4 CHANGE: * */ things.at(1));

            if (m_kana == "hiragana") {
                m_hiragana[romaji] = thekana;
            } else if (m_kana == "katakana") {
                m_katakana[romaji] = thekana;
            }
        }
    }
    f.close();

    m_kana = "english";
}

KRomajiEdit::~KRomajiEdit()
{
}

QMenu *KRomajiEdit::createPopupMenu()
{
    QMenu *menu;
    menu = new QMenu();
    // TODO: Get the basic editing options in here from a KLineEdit popup menu (or elsewhere?)
    menu->addSeparator();

    // Put our action group together
    QActionGroup *group = new QActionGroup(menu);

    QAction *temp;
    temp = new QAction(i18nc("@option:radio selects english translation", "English"), group);
    temp->setCheckable(true);
    menu->addAction(temp);
    if (m_kana == "english") {
        temp->setChecked(true);
    } else {
        temp->setChecked(false);
    }

    temp = new QAction(i18nc("@option:radio selects japanese translation", "Kana"), group);
    temp->setCheckable(true);
    menu->addAction(temp);
    if (m_kana == "kana") {
        temp->setChecked(true);
    } else {
        temp->setChecked(false);
    }

    connect(group, &QActionGroup::triggered, this, &KRomajiEdit::setKana);

    Q_EMIT aboutToShowContextMenu(menu);
    return menu;
}

// TODO allow editing not only at end
void KRomajiEdit::keyPressEvent(QKeyEvent *e)
{
    bool shift = qApp->keyboardModifiers() & Qt::ShiftModifier; // KDE4 CHANGE
    QString ji = e->text();

    if (shift && e->key() == Qt::Key_Space) // switch hiragana/english //KDE4 CHANGE
    {
        if (m_kana == "hiragana") {
            m_kana = "english";
        } else if (m_kana == "english") {
            m_kana = "hiragana";
        }

        return;
    }

    if (m_kana == "english" || ji.isEmpty()) {
        KLineEdit::keyPressEvent(e);
        return;
    }

    if (shift) // shift for katakana
    {
        if (m_kana == "hiragana") {
            m_kana = "katakana";
        }
    }

    // kdDebug() << "--------------------\n";

    QString curEng;
    QString curKana;
    QString text = this->text();

    int i;
    unsigned int len = text.length();
    // kdDebug() << "length = " << len << endl;
    for (i = len - 1; i >= 0; i--) {
        QChar at = text.at(i);

        // kdDebug() << "at = " << QString(at) << endl;

        if (at.row() == 0 && at != QLatin1Char('.')) {
            // kdDebug() << "prepending " << QString(at) << endl;
            curEng.prepend(at);
        } else {
            break;
        }
    }
    i++;

    // kdDebug() << "i is " << i << ", length is " << len << endl;
    curKana = text.left(i);

    ji.prepend(curEng);
    ji = ji.toLower();
    // kdDebug() << "ji = " << ji << endl;

    QString replace;

    // kdDebug () << "kana is " << m_kana << endl;
    if (m_kana == "hiragana") {
        replace = m_hiragana[ji];
    } else if (m_kana == "katakana") {
        replace = m_katakana[ji];
    }

    // kdDebug() << "replace = " << replace << endl;

    if (!(replace.isEmpty())) // if (replace has something in it) //KDE4 CHANGE
    {
        // kdDebug() << "replace isn't empty\n";

        setText(curKana + replace);

        if (m_kana == "katakana") {
            m_kana = "hiragana";
        }

        return;
    } else {
        // kdDebug() << "replace is empty\n";
        QString farRight(ji.right(ji.length() - 1));
        // kdDebug() << "ji = " << ji << endl;
        // kdDebug() << "farRight = " << farRight << endl;

        // test if we need small tsu
        if (ji.at(0) == farRight.at(0)) // if two letters are same, and we can add a twoletter length kana
        {
            if (m_kana == "hiragana") {
                setText(curKana + m_hiragana[ji.at(0) == QLatin1Char('n') ? "n'" : "t-"] + farRight.at(0));
            } else {
                setText(curKana + m_katakana[ji.at(0) == QLatin1Char('n') ? "n'" : "t-"] + farRight.at(0));
            }

            if (m_kana == "katakana") {
                m_kana = "hiragana";
            }

            return;
        }

        // test for hanging n
        QString newkana;
        if (m_kana == "hiragana") {
            newkana = m_hiragana[farRight];
            // kdDebug() << "newkana = " << newkana << endl;
            if (ji.at(0) == QLatin1Char('n') && !(newkana.isEmpty())) // KDE4 CHANGE
            {
                // kdDebug() << "doing the n thing\n";

                setText(curKana + m_hiragana[QStringLiteral("n'")] + newkana);

                if (m_kana == "katakana") {
                    m_kana = "hiragana";
                }

                return;
            }
        } else {
            newkana = m_katakana[farRight];
            if (ji.at(0) == QLatin1Char('n') && !newkana.isEmpty()) // KDE4 CHANGE
            {
                // kdDebug() << "doing the n thing - katakana\n";

                setText(curKana + m_katakana[QStringLiteral("n'")] + newkana);

                if (m_kana == "katakana") {
                    m_kana = "hiragana";
                }

                return;
            }
        }
    }

    if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) // take care of pending n //KDE4 CHANGE
    {
        if (m_kana == "hiragana") {
            if (text[len - 1] == QLatin1Char('n')) {
                setText(curKana + m_hiragana[QStringLiteral("n'")]);
            }
        } else {
            if (text[len - 1] == QLatin1Char('N')) {
                setText(curKana + m_katakana[QStringLiteral("n'")]);
            }
        }
    }

    KLineEdit::keyPressEvent(e); // don't think we'll get here :)
}

// This is the slot for the menu
void KRomajiEdit::setKana(QAction *action)
{
    if (action->text() == QLatin1String("Kana")) {
        m_kana = "hiragana";
    }
    if (action->text() == QLatin1String("English")) {
        m_kana = "english";
    }
}
