/***************************************************************************
                          INDI Driver
                             -------------------
    begin                : Wed May 7th 2003
    copyright            : (C) 2001 by Jasem Mutlaq
    email                : mutlaqja@ikarustech.com
 ***************************************************************************/
/***************************************************************************
 *                                                                         *
 *   This program 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.                                   *
 *                                                                         *
 ***************************************************************************/

#pragma once

#include "ui_devmanager.h"

#include <QFrame>
#include <QHash>
#include <QIcon>
#include <QList>

#include <lilxml.h>

#include <unistd.h>

class QTreeWidgetItem;

class DeviceManager;
class INDI_D;
class KStars;

struct INDIHostsInfo
{
    QString name;
    QString hostname;
    QString portnumber;
    bool isConnected { false };
    DeviceManager *deviceManager { nullptr };
};

class IDevice : public QObject
{
    Q_OBJECT

  public:
    enum DeviceStatus
    {
        DEV_START,
        DEV_TERMINATE
    };
    enum XMLSource
    {
        PRIMARY_XML,
        THIRD_PARTY_XML,
        EM_XML
    };

    IDevice(const QString &inName, const QString &inLabel, const QString &inDriver, const QString &inVersion);
    ~IDevice();

    void clear();
    QString getServerBuffer();

    QString tree_label;
    QString unique_label;
    QString name;
    QString driver;
    QString version;
    QString id;
    QString port;
    DeviceStatus state;
    XMLSource xmlSource;

    DeviceManager *deviceManager;
    int type { 0 };

    /* Telescope specific attributes */
    double focal_length { 0 };
    double aperture { 0 };
};

class DeviceManagerUI : public QFrame, public Ui::devManager
{
    Q_OBJECT

  public:
    explicit DeviceManagerUI(QWidget *parent = nullptr);

    QIcon runningPix;
    QIcon stopPix;
    QIcon connected;
    QIcon disconnected;
    QIcon localMode;
    QIcon serverMode;

  public slots:
    void makePortEditable(QTreeWidgetItem *selectedItem, int column);
};

class INDIDriver : public QDialog
{
    Q_OBJECT

  public:
    enum
    {
        LOCAL_NAME_COLUMN = 0,
        LOCAL_STATUS_COLUMN,
        LOCAL_MODE_COLUMN,
        LOCAL_VERSION_COLUMN,
        LOCAL_PORT_COLUMN
    };
    enum
    {
        HOST_STATUS_COLUMN = 0,
        HOST_NAME_COLUMN,
        HOST_PORT_COLUMN
    };

    explicit INDIDriver(KStars *ks);
    ~INDIDriver();

    bool readXMLDrivers();
    void processXMLDriver(QString &driverName);
    bool buildDeviceGroup(XMLEle *root, char errmsg[]);
    bool buildDriverElement(XMLEle *root, QTreeWidgetItem *DGroup, int groupType, char errmsg[]);

    int getINDIPort(int customPort);
    bool isDeviceRunning(const QString &deviceLabel);

    void saveHosts();

    void processLocalTree(IDevice::DeviceStatus dev_request);
    void processRemoteTree(IDevice::DeviceStatus dev_request);
    IDevice *findDeviceByLabel(const QString &label);

  public slots:
    void enableDevice(INDI_D *device);
    void disableDevice(INDI_D *device);

    void resizeDeviceColumn();
    void updateLocalTab();
    void updateClientTab();

    void updateMenuActions();

    void addINDIHost();
    void modifyINDIHost();
    void removeINDIHost();
    void activateRunService();
    void activateStopService();
    void activateHostConnection();
    void activateHostDisconnection();
    void newTelescopeDiscovered();
    void newCCDDiscovered();
    void updateCustomDrivers();

  public:
    KStars *ksw { nullptr };
    DeviceManagerUI *ui { nullptr };
    QList<IDevice *> devices;
    QTreeWidgetItem *lastGroup { nullptr };
    QTreeWidgetItem *lastDevice { nullptr };
    QHash<QString, QString> driversList;
    int currentPort { 0 };
    IDevice::XMLSource xmlSource;

  signals:
    void newDevice();
    void newTelescope();
    void newCCD();
};
