#ifndef ALTIUMPARSER_H
#define ALTIUMPARSER_H

#include <QObject>
#include <QString>
#include <QStringList>
#include <QList>
#include <QMap>
#include <QRegularExpression>
#include <QFile>
#include <QTextStream>
#include <QTextCodec>
#include <QDir>
#include <QFileInfo>
#include <QDebug>
#include <QFuture>
#include <QFutureWatcher>
#include <QtConcurrent>

// Структуры данных для парсинга
struct ComponentProperty {
    QString name;
    QString text;
};

struct VariantInfo {
    QString name;
    QStringList dnfDesignators;
    QStringList fittedDesignators;
    QList<QList<ComponentProperty>> componentVariants;
    QList<QMap<QString, QString>> parameters;
};

struct DielProperty {
    QString name;
    QString value;
    double height; // толщина материала в мм
    int dielType; // 1 - ядро, 2 - препрег
    int layerNumber; // номер слоя
};

struct ProjectParameterData {
    QString name;
    QString value;
    QString variantName;
};

// Структура для хранения данных проекта
struct ProjectData {
    QStringList variantNames;
    QList<QList<ComponentProperty>> componentsList;
    QList<QList<QList<ComponentProperty>>> componentsVariantList;
    QList<QList<ComponentProperty>> componentsPropVariantList;
    QList<ComponentProperty> componentVariantPropList;
    QStringList dnfDesignatorsList;
    QList<QStringList> dnfVariantDesignatorsList;
    QStringList fittedDesignatorsList;
    QList<QStringList> fittedVariantDesignatorsList;
    QList<QList<QStringList>> prjParamsVariantList;
    
    // PCB данные
    int pcbLayerCount;
    QList<DielProperty> pcbDielMaterials;
    QString pcbDocFileName; // Имя PcbDoc файла
    
    // Переменные состояния парсинга
    bool isWaitingVariantDescription = false;
    int currentVariantNumber = 0;
};

// Forward declarations
class DataBaseController;
class ComponentModel;

class AltiumParser : public QObject
{
    Q_OBJECT
public:
    explicit AltiumParser(QObject *parent = nullptr);
    ~AltiumParser();

    // Основные методы парсинга
    bool parseSchFile(const QString &filename, ComponentModel *model);
    bool parsePcbFile(const QString &filename, ComponentModel *model);
    bool parseBomFile(const QString &filename, ComponentModel *model);
    
    // Парсинг специфичных форматов Altium
    bool parseSchDoc(const QString &filename, ComponentModel *model);
    bool parsePcbDoc(const QString &filename, ComponentModel *model);
    QString getPcbDocFileName() const; // Получить имя PcbDoc файла после парсинга проекта
    bool parseCsvBom(const QString &filename, ComponentModel *model);
    bool parseXlsBom(const QString &filename, ComponentModel *model);
    bool parsePrjPcbFile(const QString &filename, ComponentModel *model);
    
    // Утилиты для работы с данными
    QString extractComponentDesignation(const QString &line);
    QString extractComponentName(const QString &line);
    QString extractComponentValue(const QString &line);
    QString extractComponentFootprint(const QString &line);
    QString extractComponentManufacturer(const QString &line);
    QString extractComponentPartNumber(const QString &line);
    int extractComponentQuantity(const QString &line);
    
    // Обработка ошибок
    QString lastError() const;
    void clearError();
    
    // Доступ к базе данных
    DataBaseController* getDatabase() const;
    void setDatabase(DataBaseController *database);
    
    // Асинхронный парсинг
    bool parseFileAsync(const QString &filename, ComponentModel *model);
    bool isParsingAsync() const;
    void cancelParsing();

signals:
    void parsingStarted();
    void parsingProgress(int percentage);
    void parsingFinished(bool success);
    void parsingError(const QString &error);

private:
    QString m_lastError;
    
    // Асинхронный парсинг
    QFutureWatcher<bool> *m_parseWatcher;
    bool m_isParsingAsync;
    
    // Регулярные выражения для парсинга
    QRegularExpression m_designationRegex;
    QRegularExpression m_nameRegex;
    QRegularExpression m_valueRegex;
    QRegularExpression m_footprintRegex;
    QRegularExpression m_manufacturerRegex;
    QRegularExpression m_partNumberRegex;
    QRegularExpression m_quantityRegex;
    
    // Вспомогательные методы
    void initializeRegex();
    bool parseSchLine(const QString &line, QMap<QString, QString> &component);
    bool parsePcbLine(const QString &line, QMap<QString, QString> &component);
    bool parseBomLine(const QString &line, QMap<QString, QString> &component);
    QString cleanString(const QString &str);
    bool isValidComponent(const QMap<QString, QString> &component);
    void setError(const QString &error);
    
    // Методы для парсинга PrjPcb
    bool parseProjectFile(const QString &filename, ComponentModel *model);
    bool parseSchDocFile(const QString &filename, QList<QList<ComponentProperty>> &componentsList);
    bool parsePcbDocFile(const QString &filename, QList<DielProperty> &dielMaterials, int &pcbLayersCount);
    QString makeComplexStringIfItIs(const QString &text, const QList<ComponentProperty> &componentProps);
    QString makeDesignatorForOrdering(const QString &designator);
    QString findParamDesignator(QTextStream &reader, const QString &paramNumber);
    
    // Новые методы для улучшенного парсера
    void parseProjectVariantSection(const QString &prjStr, ProjectData &data);
    void parseComponentVariations(const QString &prjStr, ProjectData &data);
    void parseProjectParameters(const QString &prevPrevPrjStr, const QString &prevPrjStr, const QString &prjStr, ProjectData &data);
    void parseSchDocFiles(const QString &prjStr, const QString &filename, ProjectData &data);
    void parsePcbDocFiles(const QString &prjStr, const QString &filename, ProjectData &data);
    void finalizeCurrentVariant(ProjectData &data);
    void parseVariationDesignator(const QStringList &prjStrArray, const QStringList &valuesArray, ProjectData &data);
    void parseParamVariation(const QStringList &prjStrArray, const QStringList &valuesArray, ProjectData &data);
    void printParsingResults(const ProjectData &data);
    void saveDataToDatabase(const ProjectData &data);
    void saveVariantsToDatabase(const ProjectData &data);
    void saveRegularComponents(const ProjectData &data);
    void saveVariantProperties(const ProjectData &data);
    void saveProjectParameters(const ProjectData &data);
    void savePCBDataToDatabase(const ProjectData &data);
    void setupModelData(const ProjectData &data, ComponentModel *model);
    
    // Слоты для асинхронного парсинга
    void onParseFinished();
    void onParseProgress(int progress);
    
    // Данные проекта Altium
    QList<QList<ComponentProperty>> m_componentsList;
    QList<VariantInfo> m_variantsList;
    QList<DielProperty> m_dielMaterialsList;
    QList<ProjectParameterData> m_projectParamsList;
    QStringList m_variantNamesList;
    bool m_isPcbMultilayer;
    QString m_pcbDocFileName; // Имя PcbDoc файла после парсинга проекта
    
    // База данных для хранения компонентов
    DataBaseController *m_database;
};

#endif // ALTIUMPARSER_H
