#include "yalgorithm.h"
#include "ychildrenthread.h"
#include <QDebug>
#include "ymfilterchildren.h"
/*
 *class YASingleton
 *
*/
YAlgorithm* YASingleton::algorithm = NULL;
YAlgorithm* YASingleton::getInstance()
{
    if(algorithm == NULL)
        algorithm = new YAlgorithm();
    return algorithm;
}

YASingleton::YASingleton()
{
}

YASingleton::~YASingleton()
{
}


/*
 *
 * Class YAFactory
 *
 */

YAFactory* YAFactory::instance = NULL;

YAFactory::YAFactory()
{
}

YAFactory::~YAFactory()
{
}

YAFactory* YAFactory::getInstance()
{
    if(instance == NULL)
        instance = new YAFactory();

    return instance;
}


YAlgorithm* YAFactory::getYAlgorithm(QMap<QString, QString> mapParam)
{
    YAlgorithm* Algorithm;
    //qDebug() << "hohoho";
    if(mapParam.value("Algorithm").compare("onedepth", Qt::CaseInsensitive) == 0)
    {
         if(!m_mapAlgorithm.contains("onedepth"))
             m_mapAlgorithm.insert("onedepth", new YAlgorithm());
         Algorithm = m_mapAlgorithm.value("onedepth");
    }
    else if(mapParam.value("Algorithm").compare("twodepth", Qt::CaseInsensitive) == 0)
    {
        if(!m_mapAlgorithm.contains("twodepth"))
            m_mapAlgorithm.insert("twodepth", new YTwoDepthAlgorithm() );
        Algorithm = m_mapAlgorithm.value("twodepth");
        //qDebug() << "two depth";
    }
    else if(mapParam.value("Algorithm").compare("nxnmatrix", Qt::CaseInsensitive) == 0)
    {
        if(!m_mapAlgorithm.contains("nxnmatrix"))
            m_mapAlgorithm.insert("nxnmatrix", new YAlgorithm());
        Algorithm = m_mapAlgorithm.value("nxnmatrix");
    }
    else if(mapParam.value("Algorithm").compare("basic", Qt::CaseInsensitive) == 0)
    {
        if(!m_mapAlgorithm.contains("basic"))
            m_mapAlgorithm.insert("basic", new YAlgorithm());
        Algorithm = m_mapAlgorithm.value("basic");
    }
    else if(mapParam.value("Algorithm").compare("platform", Qt::CaseInsensitive) == 0)
    {
        if(!m_mapAlgorithm.contains("platform"))
            m_mapAlgorithm.insert("platform", new YPlatformAlgorithm());
        Algorithm = m_mapAlgorithm.value("platform");
    }
    else if(mapParam.value("Algorithm").compare("twodeptha", Qt::CaseInsensitive) == 0)
    {
        if(!m_mapAlgorithm.contains("twodeptha"))
            m_mapAlgorithm.insert("twodeptha", new YTwoDepthAAlgorithm());
        Algorithm = m_mapAlgorithm.value("twodeptha");
    }
    else if(mapParam.value("Algorithm").compare("centerkeyword", Qt::CaseInsensitive) == 0)
    {
        if(!m_mapAlgorithm.contains("centerkeyword"))
            m_mapAlgorithm.insert("centerkeyword", new YAlgorithm());
        Algorithm = m_mapAlgorithm.value("centerkeyword");
    }
    else
    {
        Algorithm = NULL;
    }
    return Algorithm;
}

/*
 *class YAlgorithm
 *
 */

YAlgorithm::YAlgorithm()
{

}

YAlgorithm::~YAlgorithm()
{

}

QMap <QString, int> YAlgorithm::getResult()
{
    return m_mapTotalResult;
}

void YAlgorithm::setParam(QMap <QString, QString> mapParam)
{
    m_mapParam = mapParam;
}


QMutex* YAlgorithm::getMutex()
{
    return &mutex;
}

void YAlgorithm::setDataAlgorithmInterface(DataAlgorithmInterface* pDAInterface)
{
    m_pDAInterface = pDAInterface;
}

void YAlgorithm::clearParam()
{
    m_mapParam.clear();
}

void YAlgorithm::clearResult()
{
    m_mapTotalResult.clear();
}

void YAlgorithm::init()
{
    clearParam();
    clearResult();
    m_nThread = 1;
    m_pYMThread = NULL;
}


QMap <QString, int> YAlgorithm::KeywordFilter(QMap <QString, int> mapResult)
{
    QMap <QString, int> Result;

    return Result;
}

QMap <QString, int> YAlgorithm::RankFilter(QMap <QString, int> mapResult)
{
    QMap <QString, int> Result;

    return Result;
}



void YAlgorithm::EmergeThreadResult()
{
    for(int i = 0;i < getThreadNumber(); i++)
    {
        for(QMap<QString, int>::iterator iterPos = m_mapThreadResult[i]->begin(); iterPos != m_mapThreadResult[i]->end();iterPos++)
        {
            if(m_mapTotalResult.contains(iterPos.key()))
            {
                m_mapTotalResult[iterPos.key()] += iterPos.value();
            }
            else
            {
                m_mapTotalResult.insert(iterPos.key(), iterPos.value());
            }
        }
        m_mapThreadResult[i]->clear();
    }

    for(int i = 0;i < getThreadNumber(); i++)
    {
        delete m_mapThreadResult[i];
    }
    delete[] m_mapThreadResult;
}

void YAlgorithm::setThreadNumber(int nThread)
{
    m_nThread = nThread;
}

int YAlgorithm::getThreadNumber()
{
    return m_nThread;
}

void YAlgorithm::Start()
{
    if(m_mapParam.isEmpty())
        return;

    bool okThread = false;
    int nThread = m_mapParam.value("Thread").trimmed().toInt(&okThread);

    if(!okThread)
        setThreadNumber(1);
    else
        setThreadNumber(nThread);

    m_pYMThread = new YMorphereThread*[getThreadNumber()];
    for(int i = 0; i < getThreadNumber(); i++)
    {
        m_pYMThread[i] = ThreadFactory::getThread(m_mapParam);
        m_pYMThread[i]->setDataAlgorithmInterface(m_pDAInterface);
        m_pYMThread[i]->setMutex(&mutex);
        m_pYMThread[i]->setParam(m_mapParam);
    }
    for(int i = 0;i < getThreadNumber(); i++)
    {
        m_pYMThread[i]->start();
    }
    for(int i = 0;i < getThreadNumber(); i++)
    {
        m_pYMThread[i]->wait();
    }

    m_mapThreadResult = new QMap<QString, int>*[getThreadNumber()];
    for(int i = 0; i < getThreadNumber(); i++)
    {
        m_mapThreadResult[i] = new QMap<QString, int>();
    }
    for(int i = 0; i < getThreadNumber(); i++)
    {
        *m_mapThreadResult[i] = m_pYMThread[i]->getResult();
        m_pYMThread[i]->clearResult();
    }

    for(int i = 0;i < getThreadNumber(); i++)
    {
        delete m_pYMThread[i];
    }
    delete[] m_pYMThread;

    EmergeThreadResult();

    YMFilter* ymfilter = YMFilterFactory::getFilter(m_mapParam);
    //qDebug() << "EXEC";
    if(ymfilter != NULL)
    {
        ymfilter->setParam(m_mapParam);
        m_mapTotalResult = ymfilter->Exec(m_mapTotalResult);
    }
    delete ymfilter;

}

void YTwoDepthAlgorithm::Start()
{
    if(m_mapParam.isEmpty())
        return;

    bool okThread = false;
    int nThread = m_mapParam.value("Thread").trimmed().toInt(&okThread);

    if(!okThread)
        setThreadNumber(1);
    else
        setThreadNumber(nThread);

    QMap<QString, QString>mapParam = m_mapParam;

    mapParam["Algorithm"] = "onedepth";


    m_pYMThread = new YMorphereThread*[getThreadNumber()];
    for(int i = 0; i < getThreadNumber(); i++)
    {
        m_pYMThread[i] = ThreadFactory::getThread(mapParam);
        m_pYMThread[i]->setDataAlgorithmInterface(m_pDAInterface);
        m_pYMThread[i]->setMutex(&mutex);
        m_pYMThread[i]->setParam(mapParam);
    }
    for(int i = 0;i < getThreadNumber(); i++)
    {
        m_pYMThread[i]->start();
    }
    for(int i = 0;i < getThreadNumber(); i++)
    {
        m_pYMThread[i]->wait();
    }

    m_mapThreadResult = new QMap<QString, int>*[getThreadNumber()];
    for(int i = 0; i < getThreadNumber(); i++)
    {
        m_mapThreadResult[i] = new QMap<QString, int>();
    }
    for(int i = 0; i < getThreadNumber(); i++)
    {
        *m_mapThreadResult[i] = m_pYMThread[i]->getResult();
        m_pYMThread[i]->clearResult();
    }

    for(int i = 0;i < getThreadNumber(); i++)
    {
        delete m_pYMThread[i];
    }
    delete[] m_pYMThread;

    EmergeThreadResult();

    YMFilter* ymfilter = YMFilterFactory::getFilter(mapParam);
    //qDebug() << "EXEC";
    if(ymfilter != NULL)
    {
        ymfilter->setParam(m_mapParam);
        m_mapTotalResult = ymfilter->Exec(m_mapTotalResult);
    }
    delete ymfilter;




    QList<QString> listKeys = m_mapTotalResult.keys();

    QString strKeys;

    for(int i = 0; i < listKeys.count(); i++)
    {
        strKeys += (listKeys.at(i).trimmed() + " ");
    }

    strKeys = strKeys.trimmed();

    m_mapTotalResult.clear();

    m_mapParam.insert("OneDepthKeys", strKeys);
    m_pDAInterface->reset();
    m_pYMThread = new YMorphereThread*[getThreadNumber()];
    for(int i = 0; i < getThreadNumber(); i++)
    {
        m_pYMThread[i] = ThreadFactory::getThread(m_mapParam);
        m_pYMThread[i]->setDataAlgorithmInterface(m_pDAInterface);
        m_pYMThread[i]->setMutex(&mutex);
        m_pYMThread[i]->setParam(m_mapParam);
    }
    for(int i = 0;i < getThreadNumber(); i++)
    {
        m_pYMThread[i]->start();
    }
    for(int i = 0;i < getThreadNumber(); i++)
    {
        m_pYMThread[i]->wait();
    }

    m_mapThreadResult = new QMap<QString, int>*[getThreadNumber()];
    for(int i = 0; i < getThreadNumber(); i++)
    {
        m_mapThreadResult[i] = new QMap<QString, int>();
    }
    for(int i = 0; i < getThreadNumber(); i++)
    {
        *m_mapThreadResult[i] = m_pYMThread[i]->getResult();
        m_pYMThread[i]->clearResult();
    }

    for(int i = 0;i < getThreadNumber(); i++)
    {
        delete m_pYMThread[i];
    }
    delete[] m_pYMThread;

    EmergeThreadResult();

    ymfilter = YMFilterFactory::getFilter(m_mapParam);
    //qDebug() << "EXEC";
    if(ymfilter != NULL)
    {
        ymfilter->setParam(m_mapParam);
        m_mapTotalResult = ymfilter->Exec(m_mapTotalResult);
    }
    delete ymfilter;

}


void YPlatformAlgorithm::Start()
{
    if(m_mapParam.isEmpty())
        return;

    bool okThread = false;
    int nThread = m_mapParam.value("Thread").trimmed().toInt(&okThread);

    if(!okThread)
        setThreadNumber(1);
    else
        setThreadNumber(nThread);

    QMap<QString, QString>mapParam = m_mapParam;

    mapParam["Algorithm"] = "platformone";


    m_pYMThread = new YMorphereThread*[getThreadNumber()];
    for(int i = 0; i < getThreadNumber(); i++)
    {
        m_pYMThread[i] = ThreadFactory::getThread(mapParam);
        m_pYMThread[i]->setDataAlgorithmInterface(m_pDAInterface);
        m_pYMThread[i]->setMutex(&mutex);
        m_pYMThread[i]->setParam(mapParam);
    }
    for(int i = 0;i < getThreadNumber(); i++)
    {
        m_pYMThread[i]->start();
    }
    for(int i = 0;i < getThreadNumber(); i++)
    {
        m_pYMThread[i]->wait();
    }

    m_mapThreadResult = new QMap<QString, int>*[getThreadNumber()];
    for(int i = 0; i < getThreadNumber(); i++)
    {
        m_mapThreadResult[i] = new QMap<QString, int>();
    }
    for(int i = 0; i < getThreadNumber(); i++)
    {
        *m_mapThreadResult[i] = m_pYMThread[i]->getResult();
        m_pYMThread[i]->clearResult();
    }

    for(int i = 0;i < getThreadNumber(); i++)
    {
        delete m_pYMThread[i];
    }
    delete[] m_pYMThread;

    EmergeThreadResult();

    YMFilter* ymfilter = YMFilterFactory::getFilter(mapParam);
    //qDebug() << "EXEC";
    if(ymfilter != NULL)
    {
        ymfilter->setParam(m_mapParam);
        m_mapTotalResult = ymfilter->Exec(m_mapTotalResult);
    }
    delete ymfilter;




    QList<QString> listKeys = m_mapTotalResult.keys();

    QString strKeys;

    for(int i = 0; i < listKeys.count(); i++)
    {
        strKeys += (listKeys.at(i).trimmed() + " ");
    }

    strKeys = strKeys.trimmed();

    m_mapTotalResult.clear();

    m_mapParam.insert("OneDepthKeys", strKeys);
    m_pDAInterface->reset();
    m_pYMThread = new YMorphereThread*[getThreadNumber()];
    for(int i = 0; i < getThreadNumber(); i++)
    {
        m_pYMThread[i] = ThreadFactory::getThread(m_mapParam);
        m_pYMThread[i]->setDataAlgorithmInterface(m_pDAInterface);
        m_pYMThread[i]->setMutex(&mutex);
        m_pYMThread[i]->setParam(m_mapParam);
    }
    for(int i = 0;i < getThreadNumber(); i++)
    {
        m_pYMThread[i]->start();
    }
    for(int i = 0;i < getThreadNumber(); i++)
    {
        m_pYMThread[i]->wait();
    }

    m_mapThreadResult = new QMap<QString, int>*[getThreadNumber()];
    for(int i = 0; i < getThreadNumber(); i++)
    {
        m_mapThreadResult[i] = new QMap<QString, int>();
    }
    for(int i = 0; i < getThreadNumber(); i++)
    {
        *m_mapThreadResult[i] = m_pYMThread[i]->getResult();
        m_pYMThread[i]->clearResult();
    }

    for(int i = 0;i < getThreadNumber(); i++)
    {
        delete m_pYMThread[i];
    }
    delete[] m_pYMThread;

    EmergeThreadResult();

    ymfilter = YMFilterFactory::getFilter(m_mapParam);
    //qDebug() << "EXEC";
    if(ymfilter != NULL)
    {
        qDebug() << "totalresult: " << m_mapTotalResult.size();
        ymfilter->setParam(m_mapParam);
        m_mapTotalResult = ymfilter->Exec(m_mapTotalResult);
    }
    delete ymfilter;

}

void YTwoDepthAAlgorithm::Start()
{
    if(m_mapParam.isEmpty())
        return;

    bool okThread = false;
    int nThread = m_mapParam.value("Thread").trimmed().toInt(&okThread);

    if(!okThread)
        setThreadNumber(1);
    else
        setThreadNumber(nThread);

    QMap<QString, QString>mapParam = m_mapParam;

    mapParam["Algorithm"] = "onedepth";


    m_pYMThread = new YMorphereThread*[getThreadNumber()];
    for(int i = 0; i < getThreadNumber(); i++)
    {
        m_pYMThread[i] = ThreadFactory::getThread(mapParam);
        m_pYMThread[i]->setDataAlgorithmInterface(m_pDAInterface);
        m_pYMThread[i]->setMutex(&mutex);
        m_pYMThread[i]->setParam(mapParam);
    }
    for(int i = 0;i < getThreadNumber(); i++)
    {
        m_pYMThread[i]->start();
    }
    for(int i = 0;i < getThreadNumber(); i++)
    {
        m_pYMThread[i]->wait();
    }

    m_mapThreadResult = new QMap<QString, int>*[getThreadNumber()];
    for(int i = 0; i < getThreadNumber(); i++)
    {
        m_mapThreadResult[i] = new QMap<QString, int>();
    }
    for(int i = 0; i < getThreadNumber(); i++)
    {
        *m_mapThreadResult[i] = m_pYMThread[i]->getResult();
        m_pYMThread[i]->clearResult();
    }

    for(int i = 0;i < getThreadNumber(); i++)
    {
        delete m_pYMThread[i];
    }
    delete[] m_pYMThread;

    EmergeThreadResult();

    YMFilter* ymfilter = YMFilterFactory::getFilter(mapParam);
    //qDebug() << "EXEC";
    if(ymfilter != NULL)
    {
        ymfilter->setParam(m_mapParam);
        m_mapTotalResult = ymfilter->Exec(m_mapTotalResult);
    }
    delete ymfilter;


    QList<QString> listKeys = m_mapTotalResult.keys();

    QString strKeys;

    for(int i = 0; i < listKeys.count(); i++)
    {
        strKeys += (listKeys.at(i).trimmed() + " ");
    }

    strKeys = strKeys.trimmed();

    m_mapTotalResult.clear();

    m_mapParam.insert("OneDepthKeys", strKeys);
    m_pDAInterface->reset();
    m_pYMThread = new YMorphereThread*[getThreadNumber()];
    for(int i = 0; i < getThreadNumber(); i++)
    {
        m_pYMThread[i] = ThreadFactory::getThread(m_mapParam);
        m_pYMThread[i]->setDataAlgorithmInterface(m_pDAInterface);
        m_pYMThread[i]->setMutex(&mutex);
        m_pYMThread[i]->setParam(m_mapParam);
    }
    for(int i = 0;i < getThreadNumber(); i++)
    {
        m_pYMThread[i]->start();
    }
    for(int i = 0;i < getThreadNumber(); i++)
    {
        m_pYMThread[i]->wait();
    }

    m_mapThreadResult = new QMap<QString, int>*[getThreadNumber()];
    for(int i = 0; i < getThreadNumber(); i++)
    {
        m_mapThreadResult[i] = new QMap<QString, int>();
    }
    for(int i = 0; i < getThreadNumber(); i++)
    {
        *m_mapThreadResult[i] = m_pYMThread[i]->getResult();
        m_pYMThread[i]->clearResult();
    }

    for(int i = 0;i < getThreadNumber(); i++)
    {
        delete m_pYMThread[i];
    }
    delete[] m_pYMThread;

    EmergeThreadResult();

    ymfilter = YMFilterFactory::getFilter(m_mapParam);
    //qDebug() << "EXEC";
    if(ymfilter != NULL)
    {
        ymfilter->setParam(m_mapParam);
        m_mapTotalResult = ymfilter->Exec(m_mapTotalResult);
    }
    delete ymfilter;

}
