#include "sconsumer.h"
#include <QSqlQuery>
#include <QSqlDatabase>
#include <QSqlError>
#include <QDebug>
#include <QDateTime>
#include <QDate>

bool SConsumer::uploadData(int _companyNum)
{

    QSqlDatabase dbWeb = m_pSInitializer->getDatabase(SDBManager::E_DATABASE_WEB);
    m_pSInitializer->insertLog("Start Consumer upload");
    m_pSInitializer->updateWebDBInfoState(dbWeb, _companyNum, "Consumer (Start)");
    if (!m_SBodyConsumerMap.uploadData(dbWeb, _companyNum))
    {
        m_pSInitializer->insertLog("Fail to upload body_consumer_map");
        return false;
    }
    if (!m_SStatsConUserBuzzybyday.uploadData(dbWeb, _companyNum))
    {
        m_pSInitializer->insertLog("Fail to upload stats_con_user_buzzbyday");
        return false;
    }
    m_pSInitializer->insertLog("End Consumer upload");
    m_pSInitializer->updateWebDBInfoState(dbWeb, _companyNum, "Consumer (Finish)");
    return true;
}

bool SConsumer::makeCategory(SDatagroup &_datagroup, int _nCategory, const QList<SInitializer::stFilter> &_listFilter)
{
    QVector<QStringList> vecData[SInitializer::E_ARTICLE_MAX];
    bool bFiltered[SInitializer::E_ARTICLE_MAX];

    for (int i = 0; i < SInitializer::E_ARTICLE_MAX; i++)
        bFiltered[i] = false;
    _datagroup.copyData(vecData);
    foreach (const SInitializer::stFilter& filter, _listFilter)
    {
        switch(filter.m_nType)
        {
        case E_FILTER_TYPE_DATE://Date
            m_SFilterAlgorithm.FilterDate(vecData, bFiltered, filter.m_vData.toString(),
                                          m_pSInitializer->getColumnIntArray()[SInitializer::E_DATA_article_date]);

            break;
        case E_FILTER_TYPE_SEARCH:
            m_SFilterAlgorithm.FilterSearch(vecData, bFiltered, filter.m_vData.toString());

            break;
        case E_FILTER_TYPE_LENGTH:
            m_SFilterAlgorithm.FilterLength(vecData, bFiltered, filter.m_vData.toString());
            break;
        case E_FILTER_TYPE_REPLACE:
            m_SFilterAlgorithm.FilterReplace(vecData, bFiltered, filter.m_vData.toString());
            break;
        case E_FILTER_TYPE_COUNTER:
            m_SFilterAlgorithm.FilterCounter(vecData, bFiltered, filter.m_vData.toString());
            break;
        }
    }
    stReal streal;
    m_pSInitializer->insertLog(QString("CategoryNum:") + QString::number(_nCategory) + ",(" +
                               QString::number(vecData[SInitializer::E_ARTICLE_BODY].size()) + '/' + QString::number(vecData[SInitializer::E_ARTICLE_REPLY].size()) + ")" + "(Body/Reply)" );
    const int *anColumn = m_pSInitializer->getColumnIntArray();
    if (bFiltered[SInitializer::E_ARTICLE_BODY])
    {
        foreach (const QStringList& strlist, vecData[SInitializer::E_ARTICLE_BODY])
        {
            streal.m_setRealAllUrl.insert(strlist[anColumn[SInitializer::E_DATA_article_url]].trimmed());
            streal.m_setRealBodyUrl.insert(strlist[anColumn[SInitializer::E_DATA_article_url]].trimmed());
            _datagroup.addRealUrl(strlist[anColumn[SInitializer::E_DATA_article_url]].trimmed());
        }
    }

    if (bFiltered[SInitializer::E_ARTICLE_REPLY])
    {
        foreach (const QStringList& strlist, vecData[SInitializer::E_ARTICLE_REPLY])
        {
            streal.m_setRealAllUrl.insert(strlist[anColumn[SInitializer::E_DATA_article_url]].trimmed());
            streal.m_mapRealReplyUniqueUrl.insertMulti(strlist[anColumn[SInitializer::E_DATA_article_url]].trimmed(),
                    strlist[anColumn[SInitializer::E_DATA_article_order]].trimmed().toInt());
            _datagroup.addRealUrl(strlist[anColumn[SInitializer::E_DATA_article_url]].trimmed());
        }
    }

    m_mapCategory.insert(_nCategory, streal);
    return true;
}

bool SConsumer::changeTable(int _companyNum)
{
    m_pSInitializer->insertLog("Start change consumer tables");
    QSqlDatabase dbWeb = m_pSInitializer->getDatabase(SDBManager::E_DATABASE_WEB);
    if (!m_SBodyConsumerMap.changeTable(dbWeb, _companyNum))
    {
        m_pSInitializer->insertLog("Fail to body_consumer_change");
        return false;
    }

    return true;
}

void SConsumer::setInitiaizer(SInitializer &_initializer)
{
    m_pSInitializer = &_initializer;
    m_SBodyConsumerMap.setInitiaizer(_initializer);
    m_SStatsConUserBuzzybyday.setInitiaizer(_initializer);
}

bool SConsumer::makeOverallCategory(int _nCategory)
{
    if (m_mapCategory.size() < 1)
        return true;

    stReal streal;
    for (QMap<int, stReal>::iterator iterPos = m_mapCategory.begin(); iterPos != m_mapCategory.end(); iterPos++ )
    {
        stReal& val = iterPos.value();
        foreach (const QString& _strurl, val.m_setRealBodyUrl )
            streal.m_setRealBodyUrl.insert(_strurl);
        foreach (const QString& _strurl, val.m_setRealAllUrl )
            streal.m_setRealAllUrl.insert(_strurl);

        for (QMap<QString, int>::iterator iterPos1 = val.m_mapRealReplyUniqueUrl.begin(); iterPos1 != val.m_mapRealReplyUniqueUrl.end();
             iterPos1++)
        {
            streal.m_mapRealReplyUniqueUrl.insertMulti(iterPos1.key(), iterPos1.value());
        }
    }

    m_mapCategory.insert(_nCategory, streal);
    return true;
}

bool SConsumer::makeTable(SDatagroup &_datagroup)
{
    if (m_mapCategory.size() > 1)
    {
        m_pSInitializer->insertLog("Make Consumer Tables");
        m_SBodyConsumerMap.makeTable(_datagroup, m_mapCategory);
        m_pSInitializer->insertLog("Make Body Tables");
        m_SStatsConUserBuzzybyday.makeTable(_datagroup, m_mapCategory);
        m_pSInitializer->insertLog("Make Reply Tables");
    }
    return true;
}

void SConsumer::SBodyConsumerMap::makeTable(SDatagroup &_datagroup, const QMap<int, stReal> &_mapCategory)
{
    int num = 0;
    const QStringList* orderedUrl = _datagroup.getOrderedUrl();
    for (QMap<int, stReal>::const_iterator iterPos = _mapCategory.constBegin(); iterPos != _mapCategory.constEnd(); iterPos++)
    {
        const stReal& streal = iterPos.value();
        foreach (const QString& strUrl, *orderedUrl)
        {
            if (streal.m_setRealBodyUrl.contains(strUrl))
            {
                stBodyConsumerMap stbody;
                stbody.num = num++;
                stbody.body_num = _datagroup.getstBodyNum(strUrl);
                stbody.category_num = iterPos.key();
                stbody.realin |= REAL_BODY;

                stbody.platformname_num = _datagroup.getstBody(strUrl)->platformname_num;
                stbody.platformform_num = _datagroup.getstBody(strUrl)->platformform_num;
                stbody.body_date = _datagroup.getstBody(strUrl)->date;
                stbody.body_replycount = _datagroup.getstBody(strUrl)->replycount;
                stbody.body_view = _datagroup.getstBody(strUrl)->view;
                stbody.body_id_num = _datagroup.getstBody(strUrl)->id_num;

                if (streal.m_mapRealReplyUniqueUrl.contains(strUrl))
                {
                    stbody.realin |= REAL_REPLY;

                    foreach (int order, streal.m_mapRealReplyUniqueUrl.values(strUrl))
                    {
                        _datagroup.addRealReplyCategory(strUrl, order, iterPos.key());
                    }
                }
                m_listMap.append(stbody);
                _datagroup.addRealBodyCategory(strUrl, iterPos.key());
            }
            else if (streal.m_mapRealReplyUniqueUrl.contains(strUrl))
            {
                stBodyConsumerMap stbody;
                stbody.num = num++;
                stbody.body_num = _datagroup.getstBodyNum(strUrl);
                stbody.category_num = iterPos.key();
                stbody.realin |= REAL_REPLY;

                stbody.platformname_num = _datagroup.getstBody(strUrl)->platformname_num;
                stbody.platformform_num = _datagroup.getstBody(strUrl)->platformform_num;
                stbody.body_date = _datagroup.getstBody(strUrl)->date;
                stbody.body_replycount = _datagroup.getstBody(strUrl)->replycount;
                stbody.body_view = _datagroup.getstBody(strUrl)->view;
                stbody.body_id_num = _datagroup.getstBody(strUrl)->id_num;

                foreach (int order, streal.m_mapRealReplyUniqueUrl.values(strUrl))
                {
                    _datagroup.addRealReplyCategory(strUrl, order, iterPos.key());
                }
                m_listMap.append(stbody);
            }
        }
    }
}

bool SConsumer::SBodyConsumerMap::changeTable(QSqlDatabase &_db, const int &_nCompany)
{
    QString strQuery;
    QSqlQuery query(_db);
    strQuery = "RENAME TABLE ";
    strQuery += "body_consumer_map_" + QString::number(_nCompany) + " TO " + "body_consumer_map_" + QString::number(_nCompany) + "_temp" + ",";
    strQuery += "body_consumer_map_" + QString::number(_nCompany) + "_update" + " TO " + "body_consumer_map_" + QString::number(_nCompany) + ",";
    strQuery += "body_consumer_map_" + QString::number(_nCompany) + "_temp" + " TO " + "body_consumer_map_" + QString::number(_nCompany) + "_update";
    if (!query.exec(strQuery.toUtf8()))
    {
        m_pSInitializer->insertLog(query.lastQuery());
        m_pSInitializer->insertLog(query.lastError().text());
        return false;
    }
    return true;
}
/*
bool SConsumer::SBodyConsumerMap::uploadData(QSqlDatabase &_db, const int &_nCompany)
{
    QString strQuery = "truncate body_consumer_map_" + QString::number(_nCompany) + "_update";
    QSqlQuery query(_db);
    if (query.exec(strQuery.toUtf8()) == false)
    {
        m_pSInitializer->insertLog(query.lastQuery());
        m_pSInitializer->insertLog(query.lastError().text());
        return false;
    }

    strQuery = QString("insert into body_consumer_map_" + QString::number(_nCompany) +
                       "_update (num,body_num,category_num,realin) VALUES (:NUM,:BODY_NUM,:CATEGORY_NUM,:REALIN)");

    query.clear();
    query.prepare(strQuery.toUtf8());

    foreach (const stBodyConsumerMap& stbody, m_listMap)
    {
        query.bindValue(":NUM", stbody.num);
        query.bindValue(":BODY_NUM", stbody.body_num);
        query.bindValue(":CATEGORY_NUM", stbody.category_num);
        query.bindValue(":REALIN", stbody.realin);
        if (query.exec() == false)
        {
            m_pSInitializer->insertLog(query.lastQuery());
            m_pSInitializer->insertLog(query.lastError().text());
            return false;
        }
    }
    return true;
}
*/

bool SConsumer::SBodyConsumerMap::uploadData(QSqlDatabase &_db, const int &_nCompany)
{
    QString strQuery = "truncate body_consumer_map_" + QString::number(_nCompany) + "_update";
    QSqlQuery query(_db);
    if (query.exec(strQuery.toUtf8()) == false)
    {
        m_pSInitializer->insertLog(query.lastQuery());
        m_pSInitializer->insertLog(query.lastError().text());
        return false;
    }

    strQuery = QString("insert into body_consumer_map_" + QString::number(_nCompany) +
                       "_update (num,body_num,category_num,realin,platformname_num,platformform_num,body_date,body_replycount,body_view,body_id_num) VALUES (");

    query.clear();

    foreach (const stBodyConsumerMap& stbody, m_listMap)
    {
        QString str = strQuery;
        str += QString::number(stbody.num) + ",";
        str += QString::number(stbody.body_num) + ",";
        str += QString::number(stbody.category_num) + ",";
        str += QString::number(stbody.realin) + ",";
        str += QString::number(stbody.platformname_num) + ",";
        str += QString::number(stbody.platformform_num) + ",";
        str += "'" + stbody.body_date + "',";
        str += QString::number(stbody.body_replycount) + ",";
        str += QString::number(stbody.body_view) + ",";
        str += QString::number(stbody.body_id_num) + ")";

        if (query.exec(str.toUtf8()) == false)
        {
            m_pSInitializer->insertLog(query.lastQuery());
            m_pSInitializer->insertLog(query.lastError().text());
            return false;
        }
    }
    return true;
}

void SConsumer::SReplyConsumerMap::makeTable(SDatagroup &_datagroup, const QMap<int, stReal> &_mapCategory)
{
    int num = 0;
    const QStringList* orderedUrl = _datagroup.getOrderedUrl();
    for (QMap<int, stReal>::const_iterator iterPos = _mapCategory.constBegin(); iterPos != _mapCategory.constEnd(); iterPos++)
    {
        const stReal& streal = iterPos.value();
        foreach (const QString& strUrl, *orderedUrl)
        {
            if (streal.m_setRealAllUrl.contains(strUrl))
            {
                if (_datagroup.getstBody(strUrl)->replycount == 0)
                    continue;

                const QMap<int, SDatagroup::stReply>* mapReply = _datagroup.getstReply(strUrl);

                for(QMap<int, SDatagroup::stReply>::const_iterator iterPos1 = mapReply->constBegin(); iterPos1 != mapReply->constEnd(); iterPos1++)
                {
                    stReplyConsumerMap streply;
                    streply.num = num++;
                    streply.category_num = iterPos.key();
                }
            }
        }
    }
}

void SConsumer::SStatsConUserBuzzybyday::makeTable(SDatagroup &_datagroup, const QMap<int, stReal> &_mapCategory)
{
    /*
    const QMap<QString, QStringList>* mapBody = _datagroup.getmapBody();
    const QMap<QString, QMap<int, QStringList> >* mapReply = _datagroup.getmapReply();
    const int* anColumn = m_pSInitializer->getColumnIntArray();

    QDate dateStart(2100,1,1),dateEnd(2000,1,1);

    QMap<int, int>* mapConsumerCategory = m_pSInitializer->getConsumerCategory();
    QList<stBuzzy> listBuzzy;
    //filtered buzzy
    {
        for (QMap<int, stReal>::const_iterator iterPos = _mapCategory.constBegin(); iterPos != _mapCategory.constEnd(); iterPos++)
        {
            stBuzzy stbuzzy;
            stbuzzy.m_nCategory = (*mapConsumerCategory)[iterPos.key()];
            const stReal &streal = iterPos.value();
            foreach (const QString& strUrl, streal.m_setRealBodyUrl)
            {
                QDate date = QDateTime::fromString((*mapBody)[strUrl.trimmed()][anColumn[SInitializer::E_DATA_article_date]].trimmed().replace("T", " "), "yyyy-MM-dd HH:mm:ss").date();
                //if (date.isNull())
                //    date = QDateTime::fromString((*mapBody)[strUrl.trimmed()][anColumn[SInitializer::E_DATA_article_date]].trimmed(), "yyyy-MM-dd HH:mm:ss").date();
                if (date.year() == 1990)
                    continue;
                dateStart = (date < dateStart ) ? date : dateStart;
                dateEnd = (date > dateEnd ) ? date : dateEnd;

                if (stbuzzy.m_mapBodyBuzz.contains(date))
                    stbuzzy.m_mapBodyBuzz[date]++;
                else
                    stbuzzy.m_mapBodyBuzz.insert(date, 1);
            }

            for (QMap<QString, int>::const_iterator iterPos1 = streal.m_mapRealReplyUniqueUrl.constBegin(); iterPos1 != streal.m_mapRealReplyUniqueUrl.constEnd(); iterPos1++)
            {
                const QStringList &slReply = (*mapReply)[iterPos1.key()][iterPos1.value()];
                QDate date = QDateTime::fromString(slReply[anColumn[SInitializer::E_DATA_article_date]].trimmed().replace("T", " "), "yyyy-MM-dd HH:mm:ss").date();
                if (date.year() == 1990)
                    continue;
                dateStart = (date < dateStart ) ? date : dateStart;
                dateEnd = (date > dateEnd ) ? date : dateEnd;
                if (stbuzzy.m_mapReplyBuzz.contains(date))
                    stbuzzy.m_mapReplyBuzz[date]++;
                else
                    stbuzzy.m_mapReplyBuzz.insert(date, 1);
            }

            listBuzzy.append(stbuzzy);
        }
    }

    //all buzzy
    {
        stBuzzy stbuzzy;
        stbuzzy.m_nCategory = 0;
        for (QMap<QString, QStringList>::const_iterator iterPos = mapBody->constBegin(); iterPos != mapBody->constEnd(); iterPos++)
        {
            QDate date = QDateTime::fromString(iterPos.value()[anColumn[SInitializer::E_DATA_article_date]].trimmed().replace("T", " "), "yyyy-MM-dd HH:mm:ss").date();
            if (date.year() == 1990)
                continue;

            if (stbuzzy.m_mapBodyBuzz.contains(date))
                stbuzzy.m_mapBodyBuzz[date]++;
            else
                stbuzzy.m_mapBodyBuzz.insert(date, 1);
        }

        for (QMap<QString, QMap<int, QStringList> >::const_iterator iterPos = mapReply->constBegin(); iterPos != mapReply->constEnd(); iterPos++)
        {
            for (QMap<int, QStringList>::const_iterator iterPos1 = iterPos.value().constBegin(); iterPos1 != iterPos.value().constEnd(); iterPos1++)
            {
                QDate date = QDateTime::fromString(iterPos1.value()[anColumn[SInitializer::E_DATA_article_date]].trimmed().replace("T", " "), "yyyy-MM-dd HH:mm:ss").date();
                if (date.year() == 1990)
                    continue;

                if (stbuzzy.m_mapReplyBuzz.contains(date))
                    stbuzzy.m_mapReplyBuzz[date]++;
                else
                    stbuzzy.m_mapReplyBuzz.insert(date, 1);
            }
        }
        listBuzzy.append(stbuzzy);
    }

    {
        for (QDate i = dateStart; i <= dateEnd; i = i.addDays(1))
        {
            //body
            stStatsConUserBuzzybyday stbodybuzz;
            stStatsConUserBuzzybyday streplybuzz;
            stStatsConUserBuzzybyday stallbuzz;
            foreach (const stBuzzy& stbuzzy, listBuzzy)
            {
                if (stbuzzy.m_mapBodyBuzz.contains(i))
                {
                    stbodybuzz.category[stbuzzy.m_nCategory] = stbuzzy.m_mapBodyBuzz[i];
                    stallbuzz.category[stbuzzy.m_nCategory] += stbuzzy.m_mapBodyBuzz[i];
                }

                if (stbuzzy.m_mapReplyBuzz.contains(i))
                {
                    streplybuzz.category[stbuzzy.m_nCategory] = stbuzzy.m_mapReplyBuzz[i];
                    stallbuzz.category[stbuzzy.m_nCategory] += stbuzzy.m_mapReplyBuzz[i];
                }
            }
            stallbuzz.date = streplybuzz.date = stbodybuzz.date = i;
            stbodybuzz.subject = "body";
            streplybuzz.subject = "reply";
            stallbuzz.subject = "all";
            m_listMap.append(stallbuzz);
            m_listMap.append(stbodybuzz);
            m_listMap.append(streplybuzz);
        }
    }
    */
}

/*
bool SConsumer::SStatsConUserBuzzybyday::changeTable(QSqlDatabase &_db, const int &_nCompany)
{

}
*/

/*
bool SConsumer::SStatsConUserBuzzybyday::uploadData(QSqlDatabase &_db, const int &_nCompany)
{
    //_db.transaction();
    QSqlQuery query(_db);
    {
        QString strQuery = "delete from stats_con_user_buzzbyday where company_num = " + QString::number(_nCompany);
        if (!query.exec(strQuery.toUtf8()))
        {
            m_pSInitializer->insertLog(query.lastQuery());
            m_pSInitializer->insertLog(query.lastError().text());
            return false;
        }
    }
    //_db.commit();
    //_db.transaction();
    QString strQuery = "insert into stats_con_user_buzzbyday (";
    for (int i = 0; i < 11; i++)
    {
        strQuery += ("category_" + QString::number(i) + ",");
    }

    strQuery += "date,subject,company_num) values (";
    for (int i = 0; i < 11; i++)
    {
        strQuery += (":category_" + QString::number(i) + ",");
    }

    strQuery += ":date,:subject,:company_num)";

    query.prepare(strQuery);

    foreach (const stStatsConUserBuzzybyday& ststats, m_listMap)
    {
        for (int i = 0; i < 11; i++)
        {
            query.bindValue(":category_" + QString::number(i), ststats.category[i]);
        }
        query.bindValue(":date", ststats.date.toString("yyyy-MM-dd"));
        query.bindValue(":subject", ststats.subject);
        query.bindValue(":company_num", _nCompany);
        if (!query.exec())
        {
            m_pSInitializer->insertLog(query.lastQuery());
            m_pSInitializer->insertLog(query.lastError().text());
            return false;
        }
    }
    //_db.commit();
    return true;
}
*/


bool SConsumer::SStatsConUserBuzzybyday::uploadData(QSqlDatabase &_db, const int &_nCompany)
{
    //_db.transaction();
    QSqlQuery query(_db);
    {
        QString strQuery = "delete from stats_con_user_buzzbyday where company_num = " + QString::number(_nCompany);
        if (!query.exec(strQuery.toUtf8()))
        {
            m_pSInitializer->insertLog(query.lastQuery());
            m_pSInitializer->insertLog(query.lastError().text());
            return false;
        }
    }
    //_db.commit();
    //_db.transaction();
    QString strQuery = "insert into stats_con_user_buzzbyday (";
    for (int i = 0; i < 11; i++)
    {
        strQuery += ("category_" + QString::number(i) + ",");
    }

    strQuery += "date,subject,company_num) values (";

    foreach (const stStatsConUserBuzzybyday& ststats, m_listMap)
    {
        QString str = strQuery;
        for (int i = 0; i < 11; i++)
        {
            str += QString::number(ststats.category[i]) + ",";
        }
        str += "'" + ststats.date.toString("yyyy-MM-dd") + "',";
        str += "'" + ststats.subject + "',";
        str += QString::number(_nCompany) + ")";
        if (!query.exec(str.toUtf8()))
        {
            m_pSInitializer->insertLog(query.lastQuery());
            m_pSInitializer->insertLog(query.lastError().text());
            return false;
        }
    }
    //_db.commit();
    return true;
}
