/*
 GigE interface for INDI based on aravis
 Copyright (C) 2016 Hendrik Beijeman (hbeyeman@gmail.com)

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#ifndef GENERIC_CCD_H
#define GENERIC_CCD_H

#include <indiccd.h>
#include <iostream>

#include "ArvInterface.h"

using namespace std;

class GigECCD : public INDI::CCD
{
  public:
    GigECCD(arv::ArvCamera *camera);
    virtual ~GigECCD();

    const char *getDefaultName();

    bool initProperties();
    bool updateProperties();

    bool Connect();
    bool Disconnect();

    bool StartExposure(float duration);
    bool AbortExposure();

  protected:
    void TimerHit();
    virtual bool UpdateCCDFrame(int x, int y, int w, int h);
    virtual bool UpdateCCDBin(int binx, int biny);
    virtual bool UpdateCCDFrameType(INDI::CCDChip::CCD_FRAME fType);

  private:
    void _delete_indi_properties(void);
    void _update_indi_properties(void);
    bool _update_geometry(void);
    void _update_image(uint8_t const *const data, size_t size);
    static void _receive_image_hook(void *const class_ptr, uint8_t const *const data, size_t size);

    void _handle_failed(void);
    void _handle_timeout(struct timeval *const tv, uint32_t timeout_us);

    arv::ArvCamera *camera;
    char name[32];
    int timer_id;
    struct timeval exposure_start_time;
    struct timeval exposure_transfer_time;

    /* Indi properties */

    INumber indiprop_gain[1];
    INumberVectorProperty indiprop_gain_prop;
    IText indiprop_info[3] {};
    ITextVectorProperty indiprop_info_prop;

    virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n);

    friend void ::ISGetProperties(const char *dev);
    friend void ::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int num);
    friend void ::ISNewText(const char *dev, const char *name, char *texts[], char *names[], int num);
    friend void ::ISNewNumber(const char *dev, const char *name, double values[], char *names[], int num);
    friend void ::ISNewBLOB(const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[],
                            char *formats[], char *names[], int n);
};

#endif // GENERIC_CCD_H
