/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Linguist of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "translator.h"

#include "simtexth.h"

#include <iostream>

#include <stdio.h>
#ifdef Q_OS_WIN
// required for _setmode, to avoid _O_TEXT streams...
# ifdef Q_OS_WINCE
#  include <stdlib.h>
# else
#  include <io.h> // for _setmode
#  include <fcntl.h> // for _O_BINARY
# endif
#endif

#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtCore/QTextCodec>
#include <QtCore/QTextStream>

#include <private/qtranslator_p.h>

QT_BEGIN_NAMESPACE

#ifdef QT_BOOTSTRAPPED
QString QObject::tr(const char *sourceText, const char *, int n)
{
    QString ret = QString::fromLatin1(sourceText);
    if (n >= 0)
        ret.replace(QLatin1String("%n"), QString::number(n));
    return ret;
}
#endif

Translator::Translator() :
    m_codec(QTextCodec::codecForName("ISO-8859-1")),
    m_locationsType(AbsoluteLocations)
{
}

void Translator::registerFileFormat(const FileFormat &format)
{
    //qDebug() << "Translator: Registering format " << format.extension;
    QList<Translator::FileFormat> &formats = registeredFileFormats();
    for (int i = 0; i < formats.size(); ++i)
        if (format.fileType == formats[i].fileType && format.priority < formats[i].priority) {
            formats.insert(i, format);
            return;
        }
    formats.append(format);
}

QList<Translator::FileFormat> &Translator::registeredFileFormats()
{
    static QList<Translator::FileFormat> theFormats;
    return theFormats;
}

void Translator::replaceSorted(const TranslatorMessage &msg)
{
    int index = find(msg);
    if (index == -1)
        appendSorted(msg);
    else
        m_messages[index] = msg;
}

void Translator::extend(const TranslatorMessage &msg)
{
    int index = find(msg);
    if (index == -1) {
        m_messages.append(msg);
    } else {
        TranslatorMessage &emsg = m_messages[index];
        emsg.addReferenceUniq(msg.fileName(), msg.lineNumber());
        if (!msg.extraComment().isEmpty()) {
            QString cmt = emsg.extraComment();
            if (!cmt.isEmpty())
                cmt.append(QLatin1String("\n----------\n"));
            cmt.append(msg.extraComment());
            emsg.setExtraComment(cmt);
        }
        if (msg.isUtf8() != emsg.isUtf8()) {
            emsg.setUtf8(true);
            emsg.setNonUtf8(true);
        }
    }
}

void Translator::append(const TranslatorMessage &msg)
{
    m_messages.append(msg);
}

void Translator::appendSorted(const TranslatorMessage &msg)
{
    int msgLine = msg.lineNumber();
    if (msgLine < 0) {
        m_messages.append(msg);
        return;
    }

    int bestIdx = 0; // Best insertion point found so far
    int bestScore = 0; // Its category: 0 = no hit, 1 = pre or post, 2 = middle
    int bestSize = 0; // The length of the region. Longer is better within one category.

    // The insertion point to use should this region turn out to be the best one so far
    int thisIdx = 0;
    int thisScore = 0;
    int thisSize = 0;
    // Working vars
    int prevLine = 0;
    int curIdx = 0;
    foreach (const TranslatorMessage &mit, m_messages) {
        bool sameFile = mit.fileName() == msg.fileName() && mit.context() == msg.context();
        int curLine;
        if (sameFile && (curLine = mit.lineNumber()) >= prevLine) {
            if (msgLine >= prevLine && msgLine < curLine) {
                thisIdx = curIdx;
                thisScore = thisSize ? 2 : 1;
            }
            ++thisSize;
            prevLine = curLine;
        } else {
            if (thisSize) {
                if (!thisScore) {
                    thisIdx = curIdx;
                    thisScore = 1;
                }
                if (thisScore > bestScore || (thisScore == bestScore && thisSize > bestSize)) {
                    bestIdx = thisIdx;
                    bestScore = thisScore;
                    bestSize = thisSize;
                }
                thisScore = 0;
                thisSize = sameFile ? 1 : 0;
                prevLine = 0;
            }
        }
        ++curIdx;
    }
    if (thisSize && !thisScore) {
        thisIdx = curIdx;
        thisScore = 1;
    }
    if (thisScore > bestScore || (thisScore == bestScore && thisSize > bestSize))
        m_messages.insert(thisIdx, msg);
    else if (bestScore)
        m_messages.insert(bestIdx, msg);
    else
        m_messages.append(msg);
}

static QString guessFormat(const QString &filename, const QString &format)
{
    if (format != QLatin1String("auto"))
        return format;

    foreach (const Translator::FileFormat &fmt, Translator::registeredFileFormats()) {
        if (filename.endsWith(QLatin1Char('.') + fmt.extension, Qt::CaseInsensitive))
            return fmt.extension;
    }

    // the default format.
    // FIXME: change to something more widely distributed later.
    return QLatin1String("ts");
}

bool Translator::load(const QString &filename, ConversionData &cd, const QString &format)
{
    cd.m_sourceDir = QFileInfo(filename).absoluteDir();
    cd.m_sourceFileName = filename;

    QFile file;
    if (filename.isEmpty() || filename == QLatin1String("-")) {
#ifdef Q_OS_WIN
        // QFile is broken for text files
# ifdef Q_OS_WINCE
        ::_setmode(stdin, _O_BINARY);
# else
        ::_setmode(0, _O_BINARY);
# endif
#endif
        if (!file.open(stdin, QIODevice::ReadOnly)) {
            cd.appendError(QString::fromLatin1("Cannot open stdin!? (%1)")
                .arg(file.errorString()));
            return false;
        }
    } else {
        file.setFileName(filename);
        if (!file.open(QIODevice::ReadOnly)) {
            cd.appendError(QString::fromLatin1("Cannot open %1: %2")
                .arg(filename, file.errorString()));
            return false;
        }
    }

    QString fmt = guessFormat(filename, format);

    foreach (const FileFormat &format, registeredFileFormats()) {
        if (fmt == format.extension) {
            if (format.loader)
                return (*format.loader)(*this, file, cd);
            cd.appendError(QString(QLatin1String("No loader for format %1 found"))
                .arg(fmt));
            return false;
        }
    }

    cd.appendError(QString(QLatin1String("Unknown format %1 for file %2"))
        .arg(format, filename));
    return false;
}


bool Translator::save(const QString &filename, ConversionData &cd, const QString &format) const
{
    QFile file;
    if (filename.isEmpty() || filename == QLatin1String("-")) {
#ifdef Q_OS_WIN
        // QFile is broken for text files
# ifdef Q_OS_WINCE
        ::_setmode(stdout, _O_BINARY);
# else
        ::_setmode(1, _O_BINARY);
# endif
#endif
        if (!file.open(stdout, QIODevice::WriteOnly)) {
            cd.appendError(QString::fromLatin1("Cannot open stdout!? (%1)")
                .arg(file.errorString()));
            return false;
        }
    } else {
        file.setFileName(filename);
        if (!file.open(QIODevice::WriteOnly)) {
            cd.appendError(QString::fromLatin1("Cannot create %1: %2")
                .arg(filename, file.errorString()));
            return false;
        }
    }

    QString fmt = guessFormat(filename, format);
    cd.m_targetDir = QFileInfo(filename).absoluteDir();

    foreach (const FileFormat &format, registeredFileFormats()) {
        if (fmt == format.extension) {
            if (format.saver)
                return (*format.saver)(*this, file, cd);
            cd.appendError(QString(QLatin1String("Cannot save %1 files")).arg(fmt));
            return false;
        }
    }

    cd.appendError(QString(QLatin1String("Unknown format %1 for file %2"))
        .arg(format).arg(filename));
    return false;
}

QString Translator::makeLanguageCode(QLocale::Language language, QLocale::Country country)
{
    QLocale locale(language, country);
    if (country == QLocale::AnyCountry) {
        QString languageCode = locale.name().section(QLatin1Char('_'), 0, 0);
        if (languageCode.length() <= 3)
            return languageCode;
        return QString();
    } else {
        return locale.name();
    }
}

void Translator::languageAndCountry(const QString &languageCode,
    QLocale::Language *lang, QLocale::Country *country)
{
    QLocale locale(languageCode);
    if (lang)
        *lang = locale.language();

    if (country) {
        if (languageCode.indexOf(QLatin1Char('_')) != -1)
            *country = locale.country();
        else
            *country = QLocale::AnyCountry;
    }
}

bool Translator::release(QFile *iod, ConversionData &cd) const
{
    foreach (const FileFormat &format, registeredFileFormats()) {
        if (format.extension == QLatin1String("qm"))
            return (*format.saver)(*this, *iod, cd);
    }
    cd.appendError(QLatin1String("No .qm saver available."));
    return false;
}

int Translator::find(const TranslatorMessage &msg) const
{
    for (int i = 0; i < m_messages.count(); ++i) {
        const TranslatorMessage &tmsg = m_messages.at(i);
        if (msg.id().isEmpty() || tmsg.id().isEmpty()) {
            if (msg.context() == tmsg.context()
                && msg.sourceText() == tmsg.sourceText()
                && msg.comment() == tmsg.comment())
                return i;
        } else {
            if (msg.id() == tmsg.id())
                return i;
        }
    }
    return -1;
}

TranslatorMessage Translator::find(const QString &context,
    const QString &comment, const TranslatorMessage::References &refs) const
{
    if (!refs.isEmpty()) {
        for (TMM::ConstIterator it = m_messages.constBegin(); it != m_messages.constEnd(); ++it) {
            if (it->context() == context && it->comment() == comment)
                foreach (const TranslatorMessage::Reference &itref, it->allReferences())
                    foreach (const TranslatorMessage::Reference &ref, refs)
                        if (itref == ref)
                            return *it;
        }
    }
    return TranslatorMessage();
}

bool Translator::contains(const QString &context) const
{
    foreach (const TranslatorMessage &msg, m_messages)
        if (msg.context() == context && msg.sourceText().isEmpty() && msg.id().isEmpty())
            return true;
    return false;
}

TranslatorMessage Translator::find(const QString &context) const
{
    foreach (const TranslatorMessage &msg, m_messages)
        if (msg.context() == context && msg.sourceText().isEmpty() && msg.id().isEmpty())
            return msg;
    return TranslatorMessage();
}

void Translator::stripObsoleteMessages()
{
    TMM newmm;
    for (TMM::ConstIterator it = m_messages.begin(); it != m_messages.end(); ++it)
        if (it->type() != TranslatorMessage::Obsolete)
            newmm.append(*it);
    m_messages = newmm;
}

void Translator::stripFinishedMessages()
{
    TMM newmm;
    for (TMM::ConstIterator it = m_messages.begin(); it != m_messages.end(); ++it)
        if (it->type() != TranslatorMessage::Finished)
            newmm.append(*it);
    m_messages = newmm;
}

void Translator::stripEmptyContexts()
{
    TMM newmm;
    for (TMM::ConstIterator it = m_messages.begin(); it != m_messages.end(); ++it)
        if (it->sourceText() != QLatin1String(ContextComment))
            newmm.append(*it);
    m_messages = newmm;
}

void Translator::stripNonPluralForms()
{
    TMM newmm;
    for (TMM::ConstIterator it = m_messages.begin(); it != m_messages.end(); ++it)
        if (it->isPlural())
            newmm.append(*it);
    m_messages = newmm;
}

void Translator::stripIdenticalSourceTranslations()
{
    TMM newmm;
    for (TMM::ConstIterator it = m_messages.begin(); it != m_messages.end(); ++it) {
        // we need to have just one translation, and it be equal to the source
        if (it->translations().count() != 1)
            newmm.append(*it);
        else if (it->translation() != it->sourceText())
            newmm.append(*it);
    }
    m_messages = newmm;
}

void Translator::dropTranslations()
{
    for (TMM::Iterator it = m_messages.begin(); it != m_messages.end(); ++it) {
        if (it->type() == TranslatorMessage::Finished)
            it->setType(TranslatorMessage::Unfinished);
        it->setTranslation(QString());
    }
}

void Translator::dropUiLines()
{
    QString uiXt = QLatin1String(".ui");
    QString juiXt = QLatin1String(".jui");
    for (TMM::Iterator it = m_messages.begin(); it != m_messages.end(); ++it) {
        QHash<QString, int> have;
        QList<TranslatorMessage::Reference> refs;
        foreach (const TranslatorMessage::Reference &itref, it->allReferences()) {
            const QString &fn = itref.fileName();
            if (fn.endsWith(uiXt) || fn.endsWith(juiXt)) {
                if (++have[fn] == 1)
                    refs.append(TranslatorMessage::Reference(fn, -1));
            } else {
                refs.append(itref);
            }
        }
        it->setReferences(refs);
    }
}

struct TranslatorMessageIdPtr {
    explicit TranslatorMessageIdPtr(const TranslatorMessage &tm)
    {
        ptr = &tm;
    }

    inline const TranslatorMessage *operator->() const
    {
        return ptr;
    }

    const TranslatorMessage *ptr;
};

Q_DECLARE_TYPEINFO(TranslatorMessageIdPtr, Q_MOVABLE_TYPE);

inline int qHash(TranslatorMessageIdPtr tmp)
{
    return qHash(tmp->id());
}

inline bool operator==(TranslatorMessageIdPtr tmp1, TranslatorMessageIdPtr tmp2)
{
    return tmp1->id() == tmp2->id();
}

struct TranslatorMessageContentPtr {
    explicit TranslatorMessageContentPtr(const TranslatorMessage &tm)
    {
        ptr = &tm;
    }

    inline const TranslatorMessage *operator->() const
    {
        return ptr;
    }

    const TranslatorMessage *ptr;
};

Q_DECLARE_TYPEINFO(TranslatorMessageContentPtr, Q_MOVABLE_TYPE);

inline int qHash(TranslatorMessageContentPtr tmp)
{
    int hash = qHash(tmp->context()) ^ qHash(tmp->sourceText());
    if (!tmp->sourceText().isEmpty())
        // Special treatment for context comments (empty source).
        hash ^= qHash(tmp->comment());
    return hash;
}

inline bool operator==(TranslatorMessageContentPtr tmp1, TranslatorMessageContentPtr tmp2)
{
    if (tmp1->context() != tmp2->context() || tmp1->sourceText() != tmp2->sourceText())
        return false;
    // Special treatment for context comments (empty source).
    if (tmp1->sourceText().isEmpty())
        return true;
    return tmp1->comment() == tmp2->comment();
}

Translator::Duplicates Translator::resolveDuplicates()
{
    Duplicates dups;
    QHash<TranslatorMessageIdPtr, int> idRefs;
    QHash<TranslatorMessageContentPtr, int> contentRefs;
    for (int i = 0; i < m_messages.count();) {
        const TranslatorMessage &msg = m_messages.at(i);
        TranslatorMessage *omsg;
        int oi;
        QSet<int> *pDup;
        if (!msg.id().isEmpty()) {
            QHash<TranslatorMessageIdPtr, int>::ConstIterator it =
                    idRefs.constFind(TranslatorMessageIdPtr(msg));
            if (it != idRefs.constEnd()) {
                oi = *it;
                omsg = &m_messages[oi];
                pDup = &dups.byId;
                goto gotDupe;
            }
        }
        {
            QHash<TranslatorMessageContentPtr, int>::ConstIterator it =
                    contentRefs.constFind(TranslatorMessageContentPtr(msg));
            if (it != contentRefs.constEnd()) {
                oi = *it;
                omsg = &m_messages[oi];
                if (msg.id().isEmpty() || omsg->id().isEmpty()) {
                    if (!msg.id().isEmpty() && omsg->id().isEmpty()) {
                        omsg->setId(msg.id());
                        idRefs[TranslatorMessageIdPtr(*omsg)] = oi;
                    }
                    pDup = &dups.byContents;
                    goto gotDupe;
                }
                // This is really a content dupe, but with two distinct IDs.
            }
        }
        if (!msg.id().isEmpty())
            idRefs[TranslatorMessageIdPtr(msg)] = i;
        contentRefs[TranslatorMessageContentPtr(msg)] = i;
        ++i;
        continue;
      gotDupe:
        if (omsg->isUtf8() != msg.isUtf8() && !omsg->isNonUtf8()) {
            // Dual-encoded message
            omsg->setUtf8(true);
            omsg->setNonUtf8(true);
        } else {
            // Duplicate
            pDup->insert(oi);
        }
        if (!omsg->isTranslated() && msg.isTranslated())
            omsg->setTranslations(msg.translations());
        m_messages.removeAt(i);
    }
    return dups;
}

void Translator::reportDuplicates(const Duplicates &dupes,
                                  const QString &fileName, bool verbose)
{
    if (!dupes.byId.isEmpty() || !dupes.byContents.isEmpty()) {
        std::cerr << "Warning: dropping duplicate messages in '" << qPrintable(fileName);
        if (!verbose) {
            std::cerr << "'\n(try -verbose for more info).\n";
        } else {
            std::cerr << "':\n";
            foreach (int i, dupes.byId)
                std::cerr << "\n* ID: " << qPrintable(message(i).id()) << std::endl;
            foreach (int j, dupes.byContents) {
                const TranslatorMessage &msg = message(j);
                std::cerr << "\n* Context: " << qPrintable(msg.context())
                          << "\n* Source: " << qPrintable(msg.sourceText()) << std::endl;
                if (!msg.comment().isEmpty())
                    std::cerr << "* Comment: " << qPrintable(msg.comment()) << std::endl;
            }
            std::cerr << std::endl;
        }
    }
}

// Used by lupdate to be able to search using absolute paths during merging
void Translator::makeFileNamesAbsolute(const QDir &originalPath)
{
    TMM newmm;
    for (TMM::iterator it = m_messages.begin(); it != m_messages.end(); ++it) {
        TranslatorMessage msg = *it;
        msg.setReferences(TranslatorMessage::References());
        foreach (const TranslatorMessage::Reference &ref, it->allReferences()) {
            QString fileName = ref.fileName();
            QFileInfo fi (fileName);
            if (fi.isRelative())
                fileName = originalPath.absoluteFilePath(fileName);
            msg.addReference(fileName, ref.lineNumber());
        }
        newmm.append(msg);
    }
    m_messages = newmm;
}

QList<TranslatorMessage> Translator::messages() const
{
    return m_messages;
}

QList<TranslatorMessage> Translator::translatedMessages() const
{
    TMM result;
    for (TMM::ConstIterator it = m_messages.begin(); it != m_messages.end(); ++it)
        if (it->type() == TranslatorMessage::Finished)
            result.append(*it);
    return result;
}

QStringList Translator::normalizedTranslations(const TranslatorMessage &msg, int numPlurals)
{
    QStringList translations = msg.translations();
    int numTranslations = msg.isPlural() ? numPlurals : 1;

    // make sure that the stringlist always have the size of the
    // language's current numerus, or 1 if its not plural
    if (translations.count() > numTranslations) {
        for (int i = translations.count(); i > numTranslations; --i)
            translations.removeLast();
    } else if (translations.count() < numTranslations) {
        for (int i = translations.count(); i < numTranslations; ++i)
            translations.append(QString());
    }
    return translations;
}

void Translator::normalizeTranslations(ConversionData &cd)
{
    bool truncated = false;
    QLocale::Language l;
    QLocale::Country c;
    languageAndCountry(languageCode(), &l, &c);
    int numPlurals = 1;
    if (l != QLocale::C) {
        QStringList forms;
        if (getNumerusInfo(l, c, 0, &forms, 0))
            numPlurals = forms.count(); // includes singular
    }
    for (int i = 0; i < m_messages.count(); ++i) {
        const TranslatorMessage &msg = m_messages.at(i);
        QStringList tlns = msg.translations();
        int ccnt = msg.isPlural() ? numPlurals : 1;
        if (tlns.count() != ccnt) {
            while (tlns.count() < ccnt)
                tlns.append(QString());
            while (tlns.count() > ccnt) {
                tlns.removeLast();
                truncated = true;
            }
            TranslatorMessage msg2(msg);
            msg2.setTranslations(tlns);
            m_messages[i] = msg2;
        }
    }
    if (truncated)
        cd.appendError(QLatin1String(
            "Removed plural forms as the target language has less "
            "forms.\nIf this sounds wrong, possibly the target language is "
            "not set or recognized."));
}

QString Translator::guessLanguageCodeFromFileName(const QString &filename)
{
    QString str = filename;
    foreach (const FileFormat &format, registeredFileFormats()) {
        if (str.endsWith(format.extension)) {
            str = str.left(str.size() - format.extension.size() - 1);
            break;
        }
    }
    static QRegExp re(QLatin1String("[\\._]"));
    while (true) {
        QLocale locale(str);
        //qDebug() << "LANGUAGE FROM " << str << "LANG: " << locale.language();
        if (locale.language() != QLocale::C) {
            //qDebug() << "FOUND " << locale.name();
            return locale.name();
        }
        int pos = str.indexOf(re);
        if (pos == -1)
            break;
        str = str.mid(pos + 1);
    }
    //qDebug() << "LANGUAGE GUESSING UNSUCCESSFUL";
    return QString();
}

bool Translator::hasExtra(const QString &key) const
{
    return m_extra.contains(key);
}

QString Translator::extra(const QString &key) const
{
    return m_extra[key];
}

void Translator::setExtra(const QString &key, const QString &value)
{
    m_extra[key] = value;
}

void Translator::setCodecName(const QByteArray &name)
{
    QTextCodec *codec = QTextCodec::codecForName(name);
    if (!codec) {
        if (!name.isEmpty())
            std::cerr << "No QTextCodec for " << name.constData() << " available. Using Latin1.\n";
        m_codec = QTextCodec::codecForName("ISO-8859-1");
    } else {
        m_codec = codec;
    }
}

QByteArray Translator::codecName() const
{
    return m_codec->name();
}

void Translator::dump() const
{
    for (int i = 0; i != messageCount(); ++i)
        message(i).dump();
}

QT_END_NAMESPACE
