/**
    05Robot - Computer Vision Module

    @author P.Kaczmarek,J.Tomczynski,T.Mankowski
    @version 1.0 2017
*/
#ifndef PROCESSOROBJECT_H
#define PROCESSOROBJECT_H 

#include <QSemaphore>
#include <QObject>
#include <QString>
#include <QList>
#include <QMetaObject>
#include <Processor.h>
#include <QTime>

#include "CameraObject.h"
#include "cxmlio.h"
/** \addtogroup ComputerVisionModule
 *  @{
 */
class CameraObject;

/**
 @brief Wrapper object containing single processor, managing its processing and control pipelines, and properties
 */
class ProcessorObject : public cXmlIO
{
	Q_OBJECT

public:
    /**
     @brief pointer to synchronisation semaphore shared across all processors
     */
	QSemaphore * syncSem;
    /**
     @brief pointer to processor instance-specific semaphore
     */
	QSemaphore * procSem;
    /**
     @brief vector of pointers to cameras connected to this processor
     */
	vector<CameraObject *> connectedDevices;
    /**
     @brief vector of pointers to processor connected to this processor
     */
	vector<ProcessorObject *> connectedProcessors;
    /**
     @brief Sets processor data, creates processor semaphore
     
     @param p pointer to Processor
     @param procType Processor type, one of ProcessorType enum
     @param procId Processor ID, unique integer
     @param ss pointer to synchronisation semaphore shared across all processors
     */
	ProcessorObject(Processor* p, int procType, int procId, QSemaphore *ss)
	{
        qRegisterMetaType<QList<ProcessorObject*>>();
        
		proc=p;
		processorType=procType;
		processorID=procId;
		
		syncSem=ss;
		procSem = new QSemaphore();
		
		isRunning = false;
    }
    /**
     @brief Default destructor, deletes corresponding Processor
     */
    ~ProcessorObject()
    {
		qDebug("deleting po");
		if(isRunning)
			proc->stop();
		delete proc;
		delete procSem;
	}
    

public:
    /**
     @brief Pointer to Processor
     */
	Processor* proc;
    /**
     @brief Processor type, one of ProcessorType enum
     */
	int processorType;
    /**
     @brief Processor ID, unique integer
     */
	int processorID;
    /**
     @brief Running flag, true while running
     */
	bool isRunning;
    /**
     @brief Passes stream to Processor for configuration writing, encapsulates it in Processor class name
     */
    virtual void writeXml(QXmlStreamWriter& stream);
    /**
     @brief Passes stream with matching class name to Processor for configuration reading
     */
    virtual void readXml(QXmlStreamReader& stream);


public slots:
    /**
     @brief Starts processor pipeline, sets isRunning to true
     */
	void pStart();
    /**
     @brief Waits for input devices semaphore, calls process in Processor
     
     @param t1 Cameras trigger time
     @param t2 Cameras acquisition finish time
     */
	void pProcess(int t1,int t2);
    /**
     @brief Calls processSpecial in Processor
     
     @param s Command string
     */
	void pProcessSpecial(QString s);

    /**
     @brief Stops processor pipeline, sets isRunning to true
     */
	void pStop();
    /**
     @brief Sets input lists
     
     @param camList list of pointers to input cameras
     @param procList list of pointers to input processors
     */
	void connectInputs(QList<CameraObject*> camList, QList<ProcessorObject*> procList);
    /**
     @brief Copies first output image to requested place, releases camera semaphore
     
     @param image pointer to cv::Mat to copy output image
     @param camSem receiver camera semaphore
     */
    void requestImage(void* image, void* camSem);

signals:
    /**
     @brief Emitted at finish of each frame processing
     
     @param id frame id (index in output vector)
     @param frame pointer to output image
     */
	void frameOut(int id, cv::Mat* frame);
    /**
     @brief Data logger
     
     @param info text to log
     */
	void writeInfo(QString);
    
private:
    QMutex output_mutex_;

};
/** @}*/
#endif
