#ifndef DATACDROM_H
#define DATACDROM_H

#include "datasetting.h"
#include "src/frame/signals.h"
#include "src/status-fix/discread.h"
#include <QObject>
#include <QIcon>
#include <QProcess>
#include <QTimer>
#include <QDebug>
class DataCDROM;

class DataMedium : public QObject
{
    Q_OBJECT
signals:
#if 0
    void empty();
    void appendale();
    void finished();
#endif
    // log
    void info(QString); void warn(QString);
    void error(QString); void debug(QString);
public:
    enum MEDIUM_TYPE
    {
        MEDIUM_UNKOWN = 0x0000,
        MEDIUM_CD_ROM = 0x0001,
        MEDIUM_CD_R = 0x0002,
        MEDIUM_CD_RW = 0x0004,
        MEDIUM_DVD_ROM = 0x0008,
        MEDIUM_DVD_R = 0x0010,
        MEDIUM_DVD_RAM = 0x0020,
        MEDIUM_DVD_R_DL_SEQ = 0x0040,
        MEDIUM_DVD_R_DL_JUMP = 0x0080,
        MEDIUM_DVD_PLUS_RW = 0x0100,
        MEDIUM_DVD_PLUS_R = 0x0101,
        MEDIUM_DVD_PLUS_RW_DL = 0x0102,
        MEDIUM_DVD_PLUS_R_DL = 0x0104,
        MEDIUM_DVD_RW_OVERWRITE = 0x0108,
        MEDIUM_DVD_RW_SEQ = 0x0110,
        MEDIUM_CD_RW_S0 = 0x0120, // in MMC-5 CD-RW has 8 subtypes.
        MEDIUM_CD_RW_S1 = 0x0140,
        MEDIUM_CD_RW_S2 = 0x0180,
        MEDIUM_CD_RW_S3 = 0x0200,
        MEDIUM_CD_RW_S4 = 0x0201,
        MEDIUM_CD_RW_S5 = 0x0202,
        MEDIUM_CD_RW_S6 = 0x0204,
        MEDIUM_CD_RW_S7 = 0x0208,
        MEDIUM_DVD_RW = 0x0210
    };
    enum MEDIUM_STATUS
    {
        MEDIUM_EMPTY = 0,
        MEDIUM_INCOMPLETE,
        MEDIUM_FINALIZED,
        MEDIUM_OTHER
    };
public:
    explicit DataMedium(QString, QString, QObject *);
    DataMedium(DataMedium &, QObject *);
    ~DataMedium();
public:
    bool isErasable() const { return m_bErasable; }
    bool isEnableUDF() const { return m_bEnableUDF; }
    QString getCapacity() const { return m_oCapacity; }
    unsigned long  get32Capacity() const { return m_u64Capacity; }
    QString getUsedCapacity() const { return m_oUsedCapacity; }
    unsigned long  get32UsedCapacity() const { return m_u64UsedCapacity; }
    QString getFreeCapacity() const { return m_oFreeCapacity; }
    unsigned long  get32FreeCapacity() const { return m_u64FreeCapacity; }
    QList<int>  getNumSpeed() const { return m_iSpeeds; }
    QStringList speeds() const { return m_oSpeeds; }
    QString display() const { return m_oDisplay; }
    MEDIUM_STATUS status() const { return (MEDIUM_STATUS)m_u8Status; }
    QIcon icon() const { return m_oIcon; }
    QString getType() const { return m_oMediumType; }
    QString getMountPoint() const { return m_oMountPoint; }
    QString getBlockName() const { return m_oBlockName; }
    void setUsedSize(unsigned long s) { m_u64UsedCapacity = s; }
    void load();
private:
    //void load();
    void type();
    void capacity();
    void speed();
    void mountPoint();
    void EnableUDF();
private:
    QString toUnitString(unsigned long);   
private slots:
    void slotsChangeBurnFormat_CDROM();
    void fixDiscStatus();
    void secondFixDiscStatus(); //检测到挂载点后，再次修正光盘状态
    void slotsMountPoint();
private:
    unsigned char    m_u8Status;
    bool             m_bAppRunning;
    bool             m_bErasable;
    bool             m_bUDF;
    //DVD光盘 且 空状态
    //m_bEnableUDF为真表示可以使用UDF格式刻录
    bool             m_bEnableUDF;
    DataCDROM       *m_oCDROM;
    unsigned int     m_u32TrackNumber;
    unsigned long    m_u64UsedCapacity;
    unsigned long    m_u64FreeCapacity;
    unsigned long    m_u64Capacity;
    QString          m_oVolumnID;
    QString          m_oBlockName;
    QString          m_oMediumType;
    QString          m_oUsedCapacity;
    QString          m_oFreeCapacity;
    QString          m_oCapacity;
    QString          m_oMountPoint;
    QString          m_oMediumName;
    QString          m_oDisplay;
    QIcon            m_oIcon;
    QList<int>       m_iSpeeds;
    QStringList      m_oSpeeds;
    DiscRead        *m_discread;
    QTimer          *m_mountPointTimer;
};


class DataCDROM : public QObject
{
    Q_OBJECT
public:
    enum BURN_MODE
    {
        BURN_CD_TAO = 0x01,
        BURN_CD_SAO = 0x02,
        BURN_CD_DAO = 0x04 // close session/track when TAO over.
    };
public:
    explicit DataCDROM(QString blockName, QObject *parent = nullptr);
    DataCDROM(DataCDROM &, QString blockName, QObject *parent = nullptr);
    static void umountMedium(QString);
    ~DataCDROM();
public:
    bool isOpen();
    void update();
    void sendMediumStatusToOtherView();
    void loadMedium();
    void umount();
    bool doorIsOpen();
    void setVolumnID(QString);
    DataCDROM * clone();
public:
    void use() { ++m_iUsing; }
    void release() { if (--m_iUsing == 0) delete this; }
public slots:
    void eject();
    void earse();
public:
    bool isCDROM() const { return m_bCDROM; }
    bool isEjected();
    bool isEnableUDF() const {return m_oMedium ? m_oMedium->isEnableUDF() : false ;}
    QString device() const { return m_oBlockName; }
    QString display() const { return m_oDisplay; }
    void updateDisplay(QString s) { if(!m_bCDROM) m_oBlockName = s; }
    QString mDisplay();
    QString getBurnFormat() const {  return m_oSetting ? m_oSetting->getBurnFormat():"ISO9660"; }
    QString mediumType() const { return m_oMedium ? m_oMedium->getType() : m_oMediumType; }
    QIcon mediumIcon();
    QIcon icon() { return QIcon::fromTheme("drive-optical"); }
    unsigned long mediumFreeSize() const { return m_oMedium ? m_oMedium->get32FreeCapacity() : 0; }
    unsigned long mediumUsedSize() const { return m_oMedium ? m_oMedium->get32UsedCapacity() : 0; }
    int mediumStatus() const { return m_oMedium ? m_oMedium->status() : -1; }
    QStringList mediumSpeed() const { return m_oMedium ? m_oMedium->speeds() : QStringList(); }
    bool mediumIsErasable() const { return m_oMedium ? m_oMedium->isErasable() : false; }
    QString mediumMountPoint() const { return m_oMedium ? m_oMedium->getMountPoint() : QString(); }
public:
    void setting() { if(m_oSetting) m_oSetting->load();}

    // 从m_oSetting中获取值
    int settingSpeed() const { return m_oSetting ? m_oSetting->getSpeed() : 0; }
    bool settingClean() const { return m_oSetting ? m_oSetting->getClean() : false; }
    bool settingCreateISO() const { return m_oSetting ? m_oSetting->getCreateISO() : false; }
    bool settingCloseSession() const { return m_oSetting ? m_oSetting->getCloseSession() : false; }
    bool settingVerficationData() const { return m_oSetting ? m_oSetting->getVerficationData() : false; }
    bool settingOpen() const { return m_oSetting ? m_oSetting->getOpen() : false; }
    QString settingPreparer() const { return m_oSetting ? m_oSetting->getPreparer() : QString(); }
    QString settingPublisher() const { return m_oSetting ? m_oSetting->getPublisher() : QString(); }
    QString settingVolumnID() const { return m_oSetting ? m_oSetting->getVolumnID() : QString(); }
    QString settingCopyright() const { return m_oSetting ? m_oSetting->getCopyright() : QString(); }
    QString settingTempPath() const { return m_oSetting ? m_oSetting->getTempPath() : QString(); }
//    QString getVendor() const {
//        qDebug()<<__func__<<__LINE__<<m_oVendor;
//        return m_oVendor;}
    // 向m_oSetting设置值
    void updateVerficationData(bool b);


public: // scsi command
    bool open();
    void close();
    bool execSCSI(const unsigned char *, const int, unsigned char *, const int);
    bool read10(  unsigned char* data,
                  unsigned int dataLen,
                  unsigned long startAdress,
                  unsigned int length,
                  bool fua=false );
public slots:
    void updateMediumUsedSize(unsigned long);
    void receiveDiscStatusChange();
private:
    void prepare();
    QString display(QString);
    //bool doorIsOpen();
    void support();
    void checkMedium();
    bool loading();
    bool checkCDROM();
private slots:
    void changeISOName(QString);
    void changeISOPath(QString);
    void slotsPrepareTimerOut();
    void slotsUpdateCDROMBurnStart(bool); //更新m_bStart状态
private:
    //int            m_iUsing;
    int            m_iHandle;
    unsigned int   m_u32MediumRSupport;
    unsigned int   m_u32MediumWSupport;
    unsigned int   m_u32BurnModeSupport;
    bool           m_bEjected;
    bool           m_bCDROM;
    bool           m_bAppRunning;
    DataSetting   *m_oSetting;
    DataMedium    *m_oMedium;
    QString        m_oDisplay;
    QString        m_oVendor;
    QString        m_oProductor;
    QString        m_oBlockName;
    QString        m_oMediumType;
    QTimer        *m_oTimer;

public:
    bool           m_bUpdateStart;//用于控制在LogincMain中addDevice和changeDevice多次调用update导致错误的成员变量
    bool           m_bStart;//用于控制在光盘刻录过程中物理弹出按键打开光盘门导致刻录流程终端的成员变量
    bool           m_bPrepare_openDevice;//prepare函数中用于防止打不开不存在设备陷入死循环的成员变量
    int            m_iUsing;//测试用，应该是私有的
signals:
    // log
    void info(QString); void warn(QString);
    void error(QString); void debug(QString);
    // medium
    void empty(); void appendale(); void finished();
    // setting
    void speed(int); void clean(bool);
    void createISO(bool);void closeSession(bool);
    void setOpen(bool); void verficationData(bool);
    void preparer(QString); void publisher(QString);
    void volumnID(QString); void copyright(QString);
    void tempPath(QString); void burnFormat(QString);
    // other
    void eject(bool);
    void updateCDROMBurnStart(bool); // 发送m_bStart状态
};

#endif // DATACDROM_H
