#ifndef TITAN_PCBCAM_JOB_H
#define TITAN_PCBCAM_JOB_H
#include "../titanpcbcamglobal.h"
#include <QObject>
#include <QDateTime>
#include <QVariant>
#include <QVariantMap>
#include "./attrdefine.h"
#include "./step.h"
#include "./layer.h"
#include "./matrixlayer.h"
#include "./symbol.h"
#include "../parser/odbfeatureparser.h"


class PcbCamJobPrivate;
class TITAN_PCBCAM_EXPORT PcbCamJob : public QObject
{
    Q_OBJECT
public:
    explicit PcbCamJob(QObject *parent = nullptr);
    ~PcbCamJob();

signals:
    void messageNotified(const QString &iMessage, const QString &iType, const QVariant &iUserData) const;
    void actionNotified(const QString &iActionName, const QVariant &iUserData) const;

public slots:
    QString jobname() const;
    void setJobname(const QString &iJobname);

    uint odbVersionMajor() const;
    void setOdbVersionMajor(uint iVersion);

    uint odbVersionMinor() const;
    void setOdbVersionMinor(uint iVersion);

    QDateTime creationDate() const;
    void setCreationDate(QDateTime iDt);

    QDateTime saveDate() const;
    void setSaveDate(QDateTime iDt);

    QString saveApp() const;
    void setSaveApp(const QString &iApp);

    QString saveUser() const;
    void setSaveUser(const QString &iUser);

    QVariant jobAttr(const QString &iName) const;
    bool hasJobAttr(const QString &iName) const;
    void setJobAttr(const QString &iName, const QVariant &iValue);

    PcbCamAttrDefine userAttrDefine(const QString &iName) const;
    QStringList userAttrDefineKeys() const;
    QList<PcbCamAttrDefine> userAttrDefineValues() const;
    void addUserAttrDefine(const PcbCamAttrDefine &iAttrDefine);

    PcbCamStep *step(const QString &iStepName) const;
    bool isStepExists(const QString &iStepName) const;
    QHash<QString, PcbCamStep*> allSteps() const;
//    void addStep(PcbCamStep *iStep);
//    void addStep(const QVector<PcbCamStep*> &iStep);
    bool createStep(const QString &iStepName);
    bool deleteStep(const QString &iStepName);
    bool renameStep(const QString &iOldStepName, const QString &iNewStepName);

    bool createLayer(const QString &iLayerName, PcbCam::LayerContext iLayerContext = PcbCam::MiscContext, const QString &iLayerType="document");

    PcbCamLayer *layer(const QString &iStepName, const QString &iLayerName);
    bool isStepLayerExists(const QString &iStepName, const QString &iLayerName) const;
    bool renameLayer(const QString &iOldLayerName, const QString &iNewLayerName);
    void setLayerType(const QString &iLayerName, const QString &iLayerType);
    void setLayerContext(const QString &iLayerName, PcbCam::LayerContext iLayerContext);
    void setLayerPolarity(const QString &iLayerName, PcbCam::Polarity iLayerPolarity);
    void setLayerSpan(const QString &iLayerName, const QString &iStartLayer, const QString &iEndLayer);
    void setLayerRow(const QString &iLayerName, int iRow);


    void setStepWorkLayer(const QString &iStepName, const QString &iLayerName);
    void setStepLayerAffected(const QString &iStepName, const QString &iLayerName, bool iAffected = true);
    void setStepLayerDisplayColor(const QString &iStepName, const QString &iLayerName, const QString iColor);
    void clearStepAffectedLayer(const QString &iStepName);
    void resetStepAttectedLayer(const QString &iStepName, const QStringList &iAffectedLayers);
    void clearStepWorkLayer(const QString &iStepName);
    void clearStepDisplayLayer(const QString &iStepName);
    PcbCamLayer *stepWorkLayer(const QString &iStepName) const;
    QList<PcbCamLayer *> stepAffectedLayer(const QString &iStepName) const;
    QList<PcbCamLayer *> stepDispalyLayer(const QString &iStepName) const;


    QString jobPath() const;
    void setJobPath(const QString &iPath);
    void setLogJobPath(const QString &iPath);

    QList<PcbCamMatrixLayer> matrixLayers() const;
    QHash<QString, int> matrixSteps() const;
    bool isLayerExists(const QString &iLayerName) const;
    PcbCamMatrixLayer matrixLayer(const QString &iLayerName) const;

    bool isSymbolExists(const QString &iSymbolName) const;
    PcbCamSymbol *symbol(const QString &iSymbolName) const;
    QHash<QString, PcbCamSymbol*> symbols() const;

    bool isFontExists(const QString &iFontName) const;
    PcbCamFont *font(const QString &iFontName) const;

    void openJob();
    void loadStepLayer(const QString &iStep, const QString &iLayer);
    void loadSymbol(const QString &iSymbolName);
    void loadFont(const QString &iFontName);

    void notifyMessage(const QString &iText, const QString &iType, const QVariant &iUserData = QVariant()) const;

    QByteArray readJobFile(const QString &iRelPath) const;
    bool importGerber274X(const QString &iGerberFile, const QString &iStep, const QString &iLayer);
    bool importDrill(const QString &iDrlFile, const QString &iStep, const QString &iLayer, const QVariantMap &iStatement);


private:
    bool readMiscInfo();
    bool readMiscAttrlist();
    bool readMiscUserattr();
    bool readMatrix();
    bool readSteps();
    QList<PcbCamOdbFeatureInfo> readLayerFeature(const QString &iStep, const QString &iLayer);
    QList<PcbCamOdbFeatureInfo> readSymbolFeature(const QString &iSymbol);
    QList<QList<PcbCamOdbFeatureInfo>> readEdaPackagesFeature(const QString &iStep);
    QList<PcbCamOdbFeatureInfo> readLayerComponent(const QString &iStep, const QString &iLayer);


    PcbCamFeature *createFeature(const PcbCamOdbFeatureInfo &iFeat);

protected:
    const QScopedPointer<PcbCamJobPrivate> d_ptr;

private:
    Q_DECLARE_PRIVATE(PcbCamJob)
    Q_DISABLE_COPY(PcbCamJob)

};

#endif // TITAN_PCBCAM_JOB_H
