#include "ProcessorObject.h"
#include <QDebug>

void ProcessorObject::writeXml(QXmlStreamWriter &stream)
{
    stream.writeStartElement(sXmlKey());
    metaDataXmlWriter(stream,*this);
    //inner elements

    proc->writeXml(stream);

    stream.writeEndElement();

}

void ProcessorObject::readXml(QXmlStreamReader &stream)
{
    cXmlIO::readXml(stream);
    while(!(stream.tokenType() == QXmlStreamReader::EndElement &&
            stream.name() == proc->sXmlKey()) && !stream.atEnd()) {
        if(stream.tokenType() == QXmlStreamReader::StartElement) {
            if(stream.name()==proc->sXmlKey()) //class name
            {
                proc->readXml(stream);
            }
        }
        stream.readNext();
    }
}


void ProcessorObject::pStart()
{
    if(isRunning)
    {
        syncSem->release(1);
        return;
    }
    isRunning = true;
    for(size_t i=0; i<proc->cameraName.size(); ++i)
        delete proc->cameraName[i];

    proc->cameraName.clear();


    for(size_t i=0; i<connectedDevices.size(); ++i)
    {
        proc->cameraName.push_back(new QString(connectedDevices[i]->cameraName));
    }

    proc->start();
    syncSem->release(1);
}

void ProcessorObject::requestImage(void* image, void* camSem)
{
    output_mutex_.lock();
    if (!proc->outputMat.empty()) {
        proc->outputMat[0]->copyTo(*(cv::Mat*)image);
    }
    ((QSemaphore*)camSem)->release(1);
    output_mutex_.unlock();
}

void ProcessorObject::pProcess(int t1,int t2)
{
    switch(proc->inputType)
    {
    case Processor::InputTypeMat:
        for(size_t i=0; i<connectedDevices.size(); ++i)
        {
            QMetaObject::invokeMethod(connectedDevices[i], "requestImage", Qt::QueuedConnection, Q_ARG(void*, proc->inputMat[i]), Q_ARG(void*, procSem) );
        }
        for(size_t i=0; i<connectedProcessors.size(); ++i)
        {
            QMetaObject::invokeMethod(connectedProcessors[i], "requestImage", Qt::QueuedConnection, Q_ARG(void*, proc->inputMat[i]), Q_ARG(void*, procSem) );
        }
        break;

    case Processor::InputTypePoint2:
        for(size_t i=0; i<connectedDevices.size(); ++i)
        {
            QMetaObject::invokeMethod(connectedDevices[i], "requestPoints2", Qt::QueuedConnection, Q_ARG(void*, proc->inputPoint2[i]), Q_ARG(void*, procSem) );
        }
        break;

    default:
        break;
    }

    procSem->acquire(connectedDevices.size()+connectedProcessors.size());
    syncSem->release(1);

    output_mutex_.lock();
    proc->process(t1,t2);

    cv::Mat* out = NULL;
    for(size_t i=0; i<proc->outputMat.size(); ++i) {
        out = new cv::Mat(*(proc->outputMat[i]));
        //		if(out->type() == CV_8UC1)
        //			cv::cvtColor(*out,*out,CV_GRAY2BGR565);
        //		if(out->type() == CV_8UC3)
        //			cv::cvtColor(*out,*out,CV_BGR2BGR565);
        emit frameOut(i, out);
    }
    output_mutex_.unlock();

    //	for(int i=0; i<proc->outputScene.size(); ++i)
    //	{
    //		emit sceneOut(i, proc->outputScene[i]);
    //	}

    //	proc->outputScene.clear();

    //syncSem->release(1);
}

void ProcessorObject::pProcessSpecial(QString s)
{
    proc->processSpecial(s.toStdString());
}

void ProcessorObject::pStop()
{
    if(!isRunning)
    {
        syncSem->release(1);
        return;
    }
    proc->stop();
    isRunning = false;
    syncSem->release(1);
}

void ProcessorObject::connectInputs(QList<CameraObject*> camList, QList<ProcessorObject*> procList)
{
    connectedDevices.clear();
    for(int i=0; i<camList.size(); ++i) {
        connectedDevices.push_back(camList[i]);
    }
    connectedProcessors.clear();
    for(int i=0; i<procList.size(); ++i) {
        connectedProcessors.push_back(procList[i]);
    }
}
