/***************************** 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 *************************************/

//
// .NAME:
//  ObjectInfo
//
// .AUTHOR:
//  Gilberto Camara, Baudoin Raoult and Fernando Ii
//
// .SUMMARY:
//  A class for handling description of PlotMod objects
//
//
// .CLIENTS:
//  Presentable
//
//
// .RESPONSABILITIES:
//  - Convert a request from the METVIEW request to the
//    macro syntax
//  - Write the contents of a PLOT_SUPERPAGE into a
//    macro file
//
// .COLLABORATORS:
//  MvRequest
//
// .BASE CLASS:
//  (none)
//
// .DERIVED CLASSES:
//  (none)
//
// .REFERENCES:
//
//
#pragma once

#include <list>
#include <map>
#include <set>
#include <string>

#include <Cached.h>
#include <Types.hpp>

class MvIcon;
class MvRequest;

using CachedList = std::list<Cached>;
using NamesMap = std::map<Cached, int>;

class ObjectInfo
{
public:
    // Constructors
    ObjectInfo() :
        hasAction_(false),
        isPrint_(false) { namesMap_.erase(namesMap_.begin(), namesMap_.end()); }

    // Class Methods
    void IsPrint(bool yesno)
    {
        isPrint_ = yesno;
    }

    void SetPlotAction()
    {
        hasAction_ = true;
    }

    bool HasAction()
    {
        return hasAction_;
    }

    void LinePrefix(const std::string& xx) { linePrefix_ = xx; }

    // Puts a new line in the description
    void PutNewLine(const Cached& newLine);

    // Format a line and a Value
    void FormatLine(const Cached&, const Cached&, const Cached&, int width = 25);
    Cached FormatValue(const char*, const char*, const Cached&);

    // Calculate maximum size of the parameters name
    int MaximumParameterNameLength(MvRequest&);

    // Writes a description into a file
    void WriteDescription(FILE* filePtr);

    // Convert a request to the macro syntax
    void ConvertRequestToMacro(MvRequest& inRequest,
                               MacroConversion lastComma,
                               Cached varName, Cached macroName,
                               std::set<Cached> skip = std::set<Cached>(),
                               bool onlySub = false);

    // Converts a data unit to macro syntax
    Cached ConvertDataUnitToMacro(MvIcon& dataUnit);

    // Converts a visdef to macro syntax
    Cached ConvertIconToMacro(MvRequest& req, Cached defVal, int id = 1);

    // Utility function, will call the correct converter
    Cached Convert(MvRequest&);

    // Static Methods
    // Find the object path associated to a request
    // which describes the object
    static Cached ObjectPath(const MvRequest&);
    static std::string ObjectFullPath(const MvRequest&);

    // Find the object name associated to a request
    // which describes the object
    static Cached ObjectName(const MvRequest&, const char* = "",
                             int id = 0, bool updateId = false,
                             bool basename = true);

    // Generate a number to tell variable names apart
    static int GenerateId(const char* name);

    // indicates if the value has characters
    static bool IsAName(const char* value);

    // indicates if the request has been called from a macro
    static bool CalledFromMacro(const MvRequest& request);

    static Cached IconClass(const MvRequest&);

    // Obtain the name of the object, without the extension
    static Cached StripExtension(const char* value);

    // Converts a name with spaces to a name with underscores
    static Cached SpaceToUnderscore(const char* nameWithSpaces);

    // Obtain the default Visdef name
    static Cached DefaultVisDefName(int treeNode);

    // Check if visdefs are from the same Class
    // EXCEPTION:  PCONT(NORMAL) and PCONT(ISOTACHS) are assumed to
    // belong from different Classes
    // Return :
    //          TRUE  : same class
    //          FALSE : different class
    static bool CheckVisDefClass(const MvRequest&, const MvRequest&);

    static Cached GenerateName(MvRequest req);

    // Find full file name, including the path
    static std::string FileName(const MvRequest&);

    // Destructor
    virtual ~ObjectInfo() = default;

private:
    CachedList description_;
    static NamesMap namesMap_;
    bool hasAction_;
    bool isPrint_;
    std::string linePrefix_;

    // No copy allowed
    ObjectInfo(const ObjectInfo&);
    ObjectInfo& operator=(const ObjectInfo&) { return *this; }
};
