/*  INDI Listener
    Copyright (C) 2012 Jasem Mutlaq (mutlaqja@ikarustech.com)

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

    Handle INDI Standard properties.
 */

#pragma once

#include "indi/indistd.h"

#include <indiproperty.h>

#include <QObject>

class ClientManager;
class FITSViewer;
class DeviceInfo;

/**
 * @class INDIListener
 * INDIListener is responsible for creating ISD::GDInterface generic devices as new devices arrive from
 * ClientManager. It can support multiple ClientManagers and will first create a generic INDI device.
 * Upon arrival of INDI properties, INDIListener can create specialized devices (e.g. Telescope) if it
 * detects key Standard INDI property that signifies a particular device family. The generic device
 * functionality is extended via the Decorator design pattern.
 *
 * INDIListener also delegates INDI properties as they are received from ClientManager to the appropriate
 * device to be processed.
 *
 * @author Jasem Mutlaq
 */
class INDIListener : public QObject
{
    Q_OBJECT

  public:
    static INDIListener *Instance();

    void addClient(ClientManager *cm);
    void removeClient(ClientManager *cm);

    ISD::GDInterface *getDevice(const QString &name);
    QList<ISD::GDInterface *> getDevices() { return devices; }

    int size() { return devices.size(); }

    bool isStandardProperty(const QString &name);

  public slots:

    void registerProperty(INDI::Property *prop);
    void removeProperty(INDI::Property *prop);
    void processDevice(DeviceInfo *dv);
    void processSwitch(ISwitchVectorProperty *svp);
    void processText(ITextVectorProperty *tvp);
    void processNumber(INumberVectorProperty *nvp);
    void processLight(ILightVectorProperty *lvp);
    void processBLOB(IBLOB *bp);
    void processMessage(INDI::BaseDevice *dp, int messageID);
    void processUniversalMessage(const QString &message);
    void removeDevice(DeviceInfo *dv);

  private:
    explicit INDIListener(QObject *parent);
    ~INDIListener();

    static INDIListener *_INDIListener;

    QList<ClientManager *> clients;
    QList<ISD::GDInterface *> devices;
    QList<ISD::ST4 *> st4Devices;

  signals:
    void newDevice(ISD::GDInterface *);
    void newTelescope(ISD::GDInterface *);
    void newCCD(ISD::GDInterface *);
    void newFilter(ISD::GDInterface *);
    void newFocuser(ISD::GDInterface *);
    void newDome(ISD::GDInterface *);
    void newWeather(ISD::GDInterface *);
    void newDustCap(ISD::GDInterface *);
    void newLightBox(ISD::GDInterface *);
    void newST4(ISD::ST4 *);
    void deviceRemoved(ISD::GDInterface *);
};
