#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "CameraPreview.h"
#include "CameraCalibrationWindow.h"
#include "SyncThread.h"
#include "UR3Workspace.h"
#include "UR3CalibWidget.h"
#include "QPropertyEditorWidget.h"
#include "ceyetrackerfilter.h"
#include <QDockWidget>

#include "ObjectManipulationWindow.h"
#include "ObjectManipulationProperties.h"
#include <QElapsedTimer>
namespace Ui {
class MainWindow;
}

/**
 @brief Example application window enabling object and image manipulation
 
 Includes Basler camera interface and two image processing modules: Processor_CameraCalibration and Processor_ObjectExtraction. Links extracted objects feed to ObjectManipulationWindow. Sets up all synchronisation relations between camera and processors. Includes three panes, selected through View menu: main image view, message log and debug interface.
 
 */
class MainWindow : public QMainWindow
{
    Q_OBJECT
    enum DeviceType { deviceImageFromFile, deviceDataFromFile, deviceBasler_GigE };
    enum ProcessorType { processorCameraCalibration, processorPlaneCalibration, processorObjectExtraction};
public:
    /**
     @brief Creates main window, installs gesture filter, opens message log pane
     
     @param parent parent widget
     */
    explicit MainWindow(QWidget *parent = 0);
    /**
     @brief Initializes all devices
        - loads specified config XML
        - connects to robot specified in config file
        - searches for available cameras and connects to first one, starts image acquisition and processing pipeline
        - on success, after 5 seconds switches to window with camera feed
     
     @param configFilename config XML name
     @param configFilename log file name
     @param is_gestures_used larger than 0 to enable gesture control
     */
    bool init(const QString &configFilename="config.xml", const QString& logFilename="", int is_gestures_used=-1);

    ~MainWindow();
private slots:
    void connectDevice();
    bool refreshDeviceList();
    void connectDevice(QListWidgetItem *selectedDev);
    /**
     @brief add message to log pane

     @param s message to display
     */
    void displayInfo(const QString &s);

    void acquisitionStart();
    void acquisitionStop();
    void updateWindowLists();
    void disconnectDevice(CameraPreview* pWindow);
    void removeProcessor(ProcessorWindow* pWindow);
        
    bool openFile(QString fileName="");
    bool saveFile(QString fileName="");
    
    void robot_connected(bool connected);
    void robot_disconnected();
    
    /* UI */
    
    void on_action_config_open_default_triggered();
    void on_action_config_open_triggered();
    void on_action_config_save_triggered();
    void on_action_config_save_as_triggered();
    void on_action_view_user_interface_triggered();
    void on_action_view_message_log_triggered();
    void on_action_view_debug_triggered();
    void on_action_robot_connect_disconnect_triggered();
    void on_action_robot_calibration_triggered();
    void on_action_robot_home_triggered();
    void on_action_camera_calibration_triggered();
    void on_action_camera_get_background_triggered();
    void on_action_camera_start_triggered();
    void on_action_camera_stop_triggered();

    void complexGesturesMatcher(int id,QRect boundingBox,QPoint center,QString description);
    void logEvent(ObjectManipulationWindow::interfaceLogEvents eventID, int selected_object, int param, QPointF point, QPointF size, float angle);
    void logEvent(cEyeTrackerFilter::logSource source,int ID,int x, int y, QString info);
    
signals:
    void syncThreadStart(int);
    void syncThreadStop();
    //
    void connectCameraToSyncThread(CameraThread *);
    void disconnectCameraFromSyncThread(CameraThread *);
    //
    void connectProcessorToSyncThread(ProcessorThread *);
    void disconnectProcessorFromSyncThread(ProcessorThread *);
    //
    void writeInfo(QString);
private:
    Ui::MainWindow *ui;
    
    bool robot_connected_ = false;
    
    SyncThread *syncThread;
    
    
    QList<CameraPreview*> connectedDevices;
    QList<ProcessorWindow*> connectedProcessors;
    
    QVector<QDockWidget*> tabs;
    
    UR3CalibWidget* UR3CalibWidget_ = NULL;
    UR3Workspace* UR3Workspace_ = NULL;
    
    Processor *PlaneCalibration_proc = NULL;
    ProcessorObject *PlaneCalibration_po = NULL;
    ProcessorThread *PlaneCalibration_pt = NULL;
    
    Processor *ObjectExtraction_proc = NULL;
    ProcessorObject *ObjectExtraction_po = NULL;
    ProcessorThread *ObjectExtraction_pt = NULL;
    
    ObjectManipulationWindow* objectManipulationWindow = NULL;
    ObjectManipulationProperties* objectManipulationProperties = NULL;
    
    cEyeTrackerFilter* gestureEventsFilter = NULL;
    QFile file;
    QTextStream stream;
    QElapsedTimer logTimer;
    
    QString configFilename_;
};

#endif // MAINWINDOW_H
