/***************************************************************************
 *   Copyright (C) 2008 by S. MANKOWSKI / G. DE BURE support@mankowski.fr  *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>  *
 ***************************************************************************/
/** @file
 * This file is Skrooge plugin for for MT940 import / export.
 *
 * @author Stephane MANKOWSKI / Guillaume DE BURE
 */
#include "skgimportpluginmt940.h"
#include "skgtraces.h"
#include "skgservices.h"
#include "skgbankincludes.h"
#include "skgobjectbase.h"
#include "skgimportexportmanager.h"

#include <QFile>
#include <qfileinfo.h>

#include <klocale.h>

/**
 * This plugin factory.
 */
K_PLUGIN_FACTORY(SKGImportPluginMT940Factory, registerPlugin<SKGImportPluginMT940>();)
/**
 * This plugin export.
 */
K_EXPORT_PLUGIN(SKGImportPluginMT940Factory("skrooge_import_mt940", "skrooge_import_mt940"))

SKGImportPluginMT940::SKGImportPluginMT940(QObject* iImporter, const QVariantList& iArg)
    : SKGImportPlugin(iImporter)
{
    SKGTRACEIN(10, "SKGImportPluginMT940::SKGImportPluginMT940");
    Q_UNUSED(iArg);
}

SKGImportPluginMT940::~SKGImportPluginMT940()
{
}

bool SKGImportPluginMT940::isImportPossible()
{
    SKGTRACEIN(10, "SKGImportPluginMT940::isImportPossible");
    return (!m_importer ? true : QFileInfo(m_importer->getFileName()).suffix().toUpper() == "MT940");
}

SKGError SKGImportPluginMT940::importFile()
{
    if (!m_importer) return SKGError(ERR_ABORT, i18nc("Error message", "Invalid parameters"));
    SKGError err;
    SKGTRACEINRC(2, "SKGImportMt940::importFile", err);
    QString iFileName = m_importer->getFileName();
    SKGTRACEL(10) << "Input filename=" << iFileName << endl;
    //Begin transaction
    err = m_importer->getDocument()->beginTransaction("#INTERNAL#" % i18nc("Import step", "Import %1 file", "MT940"), 2);
    if (!err) {
        //Open file
        if (!err) {
            QFile file(iFileName);
            if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
                err.setReturnCode(ERR_INVALIDARG);
                err.setMessage(i18nc("Error message",  "Open file '%1' failed", iFileName));
            } else {

                //Read lines
                QStringList lines;
                {
                    QTextStream stream(&file);
                    if (!m_importer->getCodec().isEmpty()) stream.setCodec(m_importer->getCodec().toAscii().constData());
                    while (!stream.atEnd()) {
                        //Read line
                        QString line = stream.readLine().trimmed();
                        if (!line.isEmpty())  lines.push_back(line);
                    }
                }
                //close file
                file.close();

                //Step 1 done
                if (!err) err = m_importer->getDocument()->stepForward(1);

                //Read lines
                bool importActivated = false;
                bool in86 = false;
                SKGAccountObject account;
                SKGOperationObject operation;
                SKGUnitObject unit;
                QString bankName = "MT940";

                int nb = lines.count();
                if (!err) err = m_importer->getDocument()->beginTransaction("#INTERNAL#" % i18nc("Import step", "Import operations"), nb);
                for (int i = 0; i < nb && !err; ++i) {
                    //Read line
                    QString line = lines.at(i);
                    if (!line.isEmpty()) {
                        if (line.startsWith(QLatin1String(":20:"))) {
                            importActivated = true;
                            in86 = false;
                            bankName = line.right(line.count() - 4);
                        } else if (importActivated) {
                            if (line.startsWith(QLatin1String(":25:"))) {
                                //Account
                                QStringList vals = SKGServices::splitCSVLine(line.right(line.count() - 4), '/');
                                QString name = "MT940";
                                QString number = name;
                                if (vals.count() == 2) {
                                    name = vals.at(0);
                                    number = vals.at(1);
                                } else if (vals.count() == 1) {
                                    name = vals.at(0);
                                    number = vals.at(0);
                                }

                                //Search if account is already existing
                                SKGObjectBase::SKGListSKGObjectBase listAccount;
                                err = m_importer->getDocument()->getObjects("v_account", "t_number='" % number % '\'', listAccount);
                                if (!err) {
                                    if (listAccount.count() == 1) {
                                        //Yes ! Only one account found
                                        account = listAccount.at(0);
                                        err = m_importer->getDocument()->sendMessage(i18nc("An information message",  "Using account '%1' for import", account.getName()));
                                    } else {
                                        if (listAccount.count() > 1) err = m_importer->getDocument()->sendMessage(i18nc("An information message",  "More than one possible account found."));

                                        SKGBankObject bank(m_importer->getDocument());
                                        if (!err) err = bank.setName(bankName);
                                        if (!err) err = bank.setNumber(bankName);
                                        if (!err && bank.load().isFailed()) err = bank.save();
                                        if (!err) err = bank.addAccount(account);
                                        if (!err) err = account.setName(name);
                                        if (!err) err = account.setNumber(number);
                                        if (!err) err = account.setType(SKGAccountObject::CURRENT);
                                        if (!err && account.load().isFailed()) err = account.save();
                                        if (!err) err = m_importer->getDocument()->sendMessage(i18nc("An information message",  "Default account '%1' created for import", name));
                                    }
                                }

                                in86 = false;
                            } else if (line.startsWith(QLatin1String(":28C:"))) {
                                in86 = false;
                            } else if (line.startsWith(QLatin1String(":60F:")) || line.startsWith(QLatin1String(":60M:"))) {
                                QString val = line.right(line.count() - 5);
                                err = SKGUnitObject::createCurrencyUnit(m_importer->getDocument(), val.mid(7, 3), unit);
                                //Example C040802EUR16,40
                                if (account.getNbOperation() > 1) {
                                    if (!err) err = m_importer->getDocument()->sendMessage(i18nc("An information message", "The initial balance of '%1' has not been set because some operations are already existing", account.getName()));
                                } else {
                                    //Set initial balance
                                    if (!err) err = account.setInitialBalance((val[0] == 'C' ? 1.0 : -1.0) * SKGServices::stringToDouble(val.right(val.count() - 10)), unit);
                                    if (!err) err = account.save();
                                    if (!err) err = m_importer->getDocument()->sendMessage(i18nc("An information message", "The initial balance of '%1' has been set with MT940 file content", account.getName()));
                                }

                                in86 = false;
                            } else if (line.startsWith(QLatin1String(":62F:")) || line.startsWith(QLatin1String(":62M:"))) {
                                in86 = false;
                            } else if (line.startsWith(QLatin1String(":61:"))) {
                                //Example :61:0712280103D000000000200,00FMSCNONREF
                                QString val = line.right(line.count() - 4);
                                QDate date = QDate::fromString(val.left(6), "yyMMdd");
                                if (date.year() < 1970) date = date.addYears(100);

                                int index = (val[10] == 'R' ? 11 : 10);
                                double sign = (val[index] == 'C' ? 1.0 : -1.0);
                                ++index;

                                if (val[index] == 'R')  ++index;

                                QString amountString;
                                while (true) {
                                    if ((val[index] >= '0' && val[index] <= '9') || val[index] == '-' || val[index] == ',') {
                                        amountString += val[index];
                                        ++index;
                                    } else {
                                        break;
                                    }
                                }

                                err = account.addOperation(operation);
                                if (!err) err = operation.setDate(date);
                                if (!err) err = operation.setUnit(unit);
                                if (!err) err = operation.setAttribute("t_imported", "T");
                                //if(!err) err = operation.setImportID("MT940");
                                if (!err) err = operation.save();

                                SKGSubOperationObject subop;
                                err = operation.addSubOperation(subop);
                                if (!err) err = subop.setQuantity(sign * SKGServices::stringToDouble(amountString));
                                if (!err) err = subop.save();

                                in86 = false;
                            } else if (line.startsWith(QLatin1String(":NS:")) && !operation.exist()) {
                                QString val = line.right(line.count() - 4);
                                QString comment = account.getComment();
                                comment += (comment.isEmpty() || val.isEmpty() ? "" : " ") % val;
                                if (!err) err = account.setComment(comment);
                                if (!err) err = account.save();
                            } else if (line.startsWith(QLatin1String(":86:")) || line.startsWith(QLatin1String(":NS:"))) {
                                QString val = line.right(line.count() - 4);
                                QString comment = operation.getComment();
                                comment += (comment.isEmpty() || val.isEmpty() ? "" : " ") % val;
                                if (!err) err = operation.setComment(comment);
                                if (!err) err = operation.save();

                                in86 = true;
                            } else if (in86) {
                                QString val = line;
                                QString comment = operation.getComment();
                                comment += (comment.isEmpty() || val.isEmpty() ? "" : " ") % val;
                                if (!err) err = operation.setComment(comment);
                                if (!err) err = operation.save();
                            }
                        }
                    }
                    if (!err) err = m_importer->getDocument()->stepForward(i + 1);
                }
                if (!err) err = m_importer->getDocument()->endTransaction(true);
                else  m_importer->getDocument()->endTransaction(false);

                //Step 2 done
                if (!err) err = m_importer->getDocument()->stepForward(2);
            }
        }
    }
    if (!err) err = m_importer->getDocument()->endTransaction(true);
    else  m_importer->getDocument()->endTransaction(false);

    return err;
}

QString SKGImportPluginMT940::getMimeTypeFilter() const
{
    return "*.mt940|" % i18nc("A file format", "MT940 file");
}

#include "skgimportpluginmt940.moc"
