#include "../tools/tools.h"

#include <EGrabber.h>

using namespace Euresys;

namespace {

class MyGrabber: public EGrabber<CallbackOnDemand> {
    public:
        MyGrabber(EGenTL &gentl)
        : EGrabber<CallbackOnDemand>(gentl)
        , frame(0)
        {
            runScript(Tools::getSampleFilePath("200-grabn-callbacks.setup.js"));
            reallocBuffers(20);
            enableEvent<DataStreamData>();
        }
        ~MyGrabber() {
            disableEvent<DataStreamData>();
            try {
                runScript(Tools::getSampleFilePath("200-grabn-callbacks.teardown.js"));
            }
            catch (...) {
            }
        }
        void go() {
            Tools::log("Grabbing...");
            start(20);
            try {
                for (int i = 0; i < 100; ++i) {
                    // get 100 events
                    // there will be new buffers and data stream events
                    processEvent< OneOf<NewBufferData, DataStreamData> >(1000);
                }
            }
            catch (const gentl_error &err) {
                if (err.gc_err == gc::GC_ERR_TIMEOUT) {
                    Tools::log("Timeout -> event loop stopped");
                } else {
                    Tools::log(std::string("GenTL exception: ") + err.what());
                    throw;
                }
            }
        }
    private:
        size_t frame;

        virtual void onNewBufferEvent(const NewBufferData& data) {
            ScopedBuffer buffer(*this, data); // wait and get a buffer
            // Note: ScopedBuffer pushes the buffer back to the input queue automatically
            // convert the buffer to BGR8
            ConvertedBuffer bgr = buffer.convert("BGR8");
            // output the converted buffer
            bgr.saveToDisk(Tools::getEnv("sample-output-path") + "/frame.NNN.jpeg", frame++);
        }

        virtual void onDataStreamEvent(const DataStreamData &data) {
            switch (data.numid) {
                case ge::EVENT_DATA_NUMID_DATASTREAM_START_OF_CAMERA_READOUT:
                    Tools::log("StartOfCameraReadout");
                    break;
                case ge::EVENT_DATA_NUMID_DATASTREAM_END_OF_CAMERA_READOUT:
                    Tools::log("EndOfCameraReadout");
                    break;
                case ge::EVENT_DATA_NUMID_DATASTREAM_START_OF_SCAN:
                    Tools::log("StartOfScan");
                    break;
                case ge::EVENT_DATA_NUMID_DATASTREAM_END_OF_SCAN:
                    Tools::log("EndOfScan");
                    break;
                case ge::EVENT_DATA_NUMID_DATASTREAM_REJECTED_FRAME:
                    Tools::log("RejectedFrame");
                    break;
                case ge::EVENT_DATA_NUMID_DATASTREAM_REJECTED_SCAN:
                    Tools::log("RejectedScan");
                    break;
                case ge::EVENT_DATA_NUMID_DATASTREAM_TRIGGER_TO_CAMERA_READOUT_TIMEOUT:
                    Tools::log("TriggerToCameraReadoutTimeout");
                    break;
                case ge::EVENT_DATA_NUMID_DATASTREAM_CAMERA_READOUT_TIMEOUT:
                    Tools::log("CameraReadoutTimeout");
                    break;
                case ge::EVENT_DATA_NUMID_DATASTREAM_BROKEN_FRAME:
                    Tools::log("BrokenFrame");
                    break;
                case ge::EVENT_DATA_NUMID_DATASTREAM_REJECTED_LINE:
                    Tools::log("RejectedLine");
                    break;
                default:
                    break;
            }
        }
};

}

static void sample() {
    EGenTL genTL;
    MyGrabber grabber(genTL);
    grabber.go();
}

static Tools::Sample addSample(__FILE__, sample, "Grab N frames and get DataStream events with callbacks");
