/***************************** LICENSE START ***********************************

 Copyright 2012 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

#pragma once

#include <fstream>
#include <map>
#include <vector>

#include "fstream_mars_fix.h"

#include <QIcon>
#include <QMap>
#include <QPair>
#include <QString>
#include <QStringList>

#include "MvIconParameter.h"
#include "MvIconLanguage.h"

class IconClassHelp;
class LanguageHelper;

/* ---------------------------------------------------------------------------------------------

    The classes defined here are for the purpose of storing the information required to
    give the user help for specific functions which follow the pattern of verb-parameters-values.
    For example, in the Macro languate, we have things such as:
      pcont (contour : 'on')

    and we want to be able to provide the user with in-editor help for these functions.

   --------------------------------------------------------------------------------------------- */


//-------------------------------------------------------------------------------------
// VerbFunctionHelpParam
// class to store all the information associated with a parameter
//-------------------------------------------------------------------------------------

class VerbFunctionHelpParam : public ParameterScanner
{
public:
    VerbFunctionHelpParam(const MvIconParameter&);
    ~VerbFunctionHelpParam() {}

    QString name() const;
    QString interface() const;
    QString interfaceFunction() const;
    QStringList defaultValues() const;
    int numValues() const;
    QString valueName(int i) const;
    void toYaml(std::ofstream&);
    const MvIconParameter& iconParam() const { return param_; }

protected:
    void next(const MvIconParameter&, const char* first, const char* second);

private:
    const MvIconParameter& param_;
    QStringList values_;
};


//-------------------------------------------------------------------------------------
// VerbFunctionHelpFunction
// class to store all the information associated with a function
//-------------------------------------------------------------------------------------

class VerbFunctionHelpFunction : public MvIconLanguageScanner
{
    friend class VerbFunctionHelp;

public:
    VerbFunctionHelpFunction(QString name, IconClassHelp* iconClass = nullptr);
    ~VerbFunctionHelpFunction();

    QString name() const { return name_; }
    QIcon icon() const;
    int numParams() const { return static_cast<int>(params_.size()); }
    QString paramName(int i) const { return params_[i]->name(); }

    VerbFunctionHelpParam* paramFromName(QString name) const;
    VerbFunctionHelpParam* param(int i) const;
    int indexOfParam(VerbFunctionHelpParam*) const;
    IconClassHelp* iconClass() const { return iconClass_; }
    bool isIconFunction() const {return iconClass_ != nullptr;}
    void loadParams();
    void setMacroOnly(bool b) {macroOnly_=b;}
    bool isMacroOnly() const {return macroOnly_;}

    QString descriptionAsStr(int idx) const;
    QString descriptionAsRt(int idx) const;
    QList<QPair<QString, QString> > descriptions() const { return descriptions_; }
    void setDescription(QString group, QString desc);

protected:
    void next(const MvIconParameter&);
    void adjustDescriptions();

private:
    QString name_;
    IconClassHelp* iconClass_;
    bool paramsLoaded_;
    std::vector<VerbFunctionHelpParam*> params_;
    std::map<QString, VerbFunctionHelpParam*> paramMap_;
    QList<QPair<QString, QString> > descriptions_;
    bool macroOnly_{false};
};

//-------------------------------------------------------------------------------------
//    The VerbFunctionHelp class allows the loading of a specially-prepared XML file with
//    all the function definitions in it (this is in its constructor). It also provides
//    the ability to query whether the given string is the name of a function for which
//    we have help available, and an accessor function to get a VerbFunctionHelpFunction
//    pointer from a given name.
//-------------------------------------------------------------------------------------

class VerbFunctionHelp
{
public:
    VerbFunctionHelp(LanguageHelper*);
    ~VerbFunctionHelp();

    void init();
    bool isEmpty() const { return functionNum() == 0; }
    int functionNum() const { return static_cast<int>(functions_.size()); }
    int totalFunctionNum() const { return totalFunctionIndex_.count(); }
    bool isHelpAvailableForFunction(QString functionName);
    VerbFunctionHelpFunction* function(QString functionName);
    QList<VerbFunctionHelpFunction*> const functions() { return functions_; }
    VerbFunctionHelpFunction* itemAt(int i) const;
    QPair<VerbFunctionHelpFunction*, int> itemAtInTotal(int i) const;
    int totalIndexOf(VerbFunctionHelpFunction* fn, int descIndex);
    QString url(VerbFunctionHelpFunction* fn, int descIndex=0);
    QString scopePrefix() const;

private:
    void clear();

    LanguageHelper* language_;
    std::map<QString, VerbFunctionHelpFunction*> functionMap_;
    QList<VerbFunctionHelpFunction*> functions_;
    QList<QPair<int, int> > totalFunctionIndex_;
    QMap<QString, QString> webIds_;
};
