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

#include <Assertions.hpp>
#include <MvPath.hpp>
#include <MvRequest.h>
#include <MvLanguage.h>
#include <MvRequestUtil.hpp>

#include "ObjectList.h"
#include "PlotModConst.h"

MvRequest&
ObjectList::Instance()
{
    static MvRequest objectList = mars.setup;  // hides the global "mars.setup"

    /*
    MvRequest reqObj = mars.setup; // hides the global "mars.setup"

    // Reads uPlot resources
    std::string filename(getenv("METVIEW_DIR_SHARE"));
    filename += "/etc/uPlotTable";
    MvRequest uPlotRes;
    uPlotRes.read(filename.c_str());

#if 0
int i = 0;
objectList.save("/tmp/dummy-user/data/ObjectList.txt");
objectList.rewind();
    while ( objectList )
    {
        i++;
        objectList.advance();
    }
    COUT << "Number total resources = " << i << std::endl;


    i = 0;
uPlotRes.save("/tmp/dummy-user/data/uPlotTable.txt");
    uPlotRes.rewind();
    while ( uPlotRes )
    {
        i++;
        uPlotRes.advance();
    }
    COUT << "Number total resources = " << i << std::endl;

i = 0;
objectList.rewind();
uPlotRes.rewind();
objectList = objectList + uPlotRes;
objectList.rewind();
    while ( objectList )
    {
        i++;
        objectList.advance();
    }
    COUT << "Number total resources = " << i << std::endl;

objectList.rewind();
objectList.save("/tmp/dummy-user/data/ObjectList1.txt");
#else
//	Merge Mars setup and uPlot object list
    reqObj.rewind();
    uPlotRes.rewind();
    reqObj = reqObj + uPlotRes;
    static MvRequest objectList = reqObj;
#endif
*/
    return objectList;
}

MvRequest
ObjectList::Find(const Cached& name, const Cached& sclass)
{
    MvRequest& objectList = ObjectList::Instance();

    objectList.rewind();
    while (objectList) {
        if (objectList.getVerb() == name &&
            objectList("class") == sclass)
            return objectList.justOneRequest();

        objectList.advance();
    }

    return {"EMPTY"};
}

// Function similar to Find, but if the request associated to this "verb"
// and "class" is not found then check if this "class" is defined in the
// "children" parameter. If yes, return the request. Otherwise, return
// an empty request.
MvRequest
ObjectList::FindPlusChildren(const char* name, const char* sclass)
{
    // Request founded
    MvRequest req = Find(Cached(name), Cached(sclass));
    if (req.getVerb() != std::string("EMPTY"))
        return req;

    // Try to find if "sclass" is defined in the "children" parameter
    MvRequest& objectList = ObjectList::Instance();
    objectList.rewind();
    int i = 0;
    while (objectList) {
        if (strcmp(objectList.getVerb(), name) == 0) {
            if ((const char*)objectList("children")) {
                for (i = 0; i < objectList.countValues("children"); i++) {
                    if (strcmp((const char*)objectList("children", i), sclass) == 0)
                        return objectList.justOneRequest();
                }
            }
        }
        objectList.advance();
    }

    return {"EMPTY"};
}

int ObjectList::FindAll(const Cached& name, MvRequest& list)
{
    MvRequest& objectList = ObjectList::Instance();
    objectList.rewind();
    int count = 0;
    while (objectList) {
        if (objectList.getVerb() == name) {
            list = list + objectList.justOneRequest();
            count++;
        }

        objectList.advance();
    }

    return count;
}

int ObjectList::FindAll(const Cached& name, const Cached& classe, MvRequest& list)
{
    MvRequest& objectList = ObjectList::Instance();
    objectList.rewind();
    int count = 0;
    while (objectList) {
        if (objectList.getVerb() == name &&
            objectList("class") == classe) {
            list = list + objectList.justOneRequest();
            count++;
        }

        objectList.advance();
    }

    return count;
}

//
// -- METHOD :  Find
//
// -- PURPOSE: Given a parameter, the method finds the list of values
//             associated to it.
//
// -- INPUT :
//
// -- OUTPUT :  This method returns ALL the values
//               as a list in Mars Languade ( ex. "VALUE1/VALUE2/VALUE3" )
Cached
ObjectList::Find(const Cached& name, const Cached& sclass, const Cached& param)
{
    MvRequest oneRequest = Find(name, sclass);
    Cached listValues = (const char*)oneRequest(param);
    Cached oneValue;
    for (int i = 1; i < oneRequest.countValues(param); i++) {
        oneRequest.getValue(oneValue, param, i);
        listValues = listValues + "/" + oneValue;
    }

    return listValues;
}

// Function similar to Find, but if the values associated to the input
// parameters are not found then check if this "class" is defined in the
// "children" parameter. If yes, return the values related to "param".
// Otherwise, return an empty string.
std::string
ObjectList::FindPlusChildren(const std::string& sname, const std::string& sclass, const std::string& sparam)
{
    // Value founded
    const char* cname = sname.c_str();
    const char* cclass = sclass.c_str();
    const char* cparam = sparam.c_str();
    const char* str = (const char*)Find(cname, cclass, cparam);
    if (str)
        return {str};

    // Try to find if "sclass" is defined in the "children" parameter
    MvRequest& objectList = ObjectList::Instance();
    objectList.rewind();
    int i = 0, j = 0;
    std::string sout;
    while (objectList) {
        if (strcmp(objectList.getVerb(), cname) == 0) {
            if ((const char*)objectList("children")) {
                for (i = 0; i < objectList.countValues("children"); i++) {
                    if (strcmp((const char*)objectList("children", i), cclass) == 0) {
                        for (j = 0; j < objectList.countValues(cparam); j++) {
                            objectList.getValue(str, cparam, j);
                            sout = sout + "/" + str;
                        }
                        return sout;
                    }
                }
            }
        }
        objectList.advance();
    }

    return sout;
}

//
// -- METHOD :  FindMainRequestValue
//
// -- PURPOSE: Given a parameter, the method finds the dominant
//             request associated to the parameter, and returns
//             the associated value
//
//             The idea here is that there is always one dominant
//             request in a list of request (PLOT_SUPERPAGE, and
//             DROP are exemples of "dominant" requests).
//
// -- INPUT  :
//
// -- OUTPUT :
Cached
ObjectList::FindMainRequestValue(const Cached& requestVerb,
                                 const Cached& parameter)
{
    return Find("request", requestVerb, parameter);
}

// -- METHOD :
//
// -- PURPOSE:
//
// -- INPUT  :
//
// -- OUTPUT :
Cached
ObjectList::FindGraphicsEngine(const MvRequest& request)
{
    // Option 1. Try to detect an Graphics Engine
    //           associated with the subrequest
    Cached geName = request("GRAPHICS_ENGINE");
    if ((const char*)geName)  // Found it
        return geName;

    // Option 2. Look for the default in the PM Table
    geName = Find("graphics_engine", "Default", "choice");
    ensure((const char*)geName != nullptr);

    return geName;
}

Cached ObjectList::FindView(const MvRequest& request)
{
    // First check if there's any view field in the request.
    // This way an application can specify which view it wants
    // if the default view for the data unit is not the right one.
    Cached viewName = request("_VIEW");

    // If not, check the given view for data unit.
    if (!(const char*)viewName)
        viewName = Find("request", request.getVerb(), "view");

    if ((const char*)viewName)
        return viewName;
    else
        return DEFAULTVIEW.c_str();
}

MvRequest
ObjectList::FindReqService(const char* classe, const char* action)
{
    const char* cval = nullptr;
    bool found = false;

    // Find all requests associate to "class"
    MvRequest reqAll;
    FindAll("state", classe, reqAll);

    // Find service related to "action"
    while (reqAll) {
        reqAll.iterInit("action");
        while (reqAll.iterGetNextValue(cval)) {
            if (!action || strcmp(cval, action) == 0) {
                found = true;
                break;
            }
        }

        if (found)
            return reqAll.justOneRequest();

        reqAll.advance();
    }

    return {};
}

std::string
ObjectList::FindService(const char* classe, const char* action)
{
    // Find request
    MvRequest req = FindReqService(classe, action);
    if (req)
        return std::string(req("service"));

    return {};
}

// -- METHOD :
//
// -- PURPOSE:
//
// -- INPUT  :
//
// -- OUTPUT :
Cached
ObjectList::DefaultVisDefClass(const char* dataUnitVerb)
{
    require(dataUnitVerb != nullptr);

    // Find out the name of the VisDef from the Plot Mod Table which
    // contains the relation between DataUnits and VisDefs
    Cached defaultVisDefClass = Find("dataunit", dataUnitVerb, "defaultVisDef");
    ensure((const char*)defaultVisDefClass != nullptr);

    return defaultVisDefClass;
}

// -- METHOD : CheckValidVisDef
//
// -- PURPOSE:
//
// -- INPUT  : 1. the name of a visDef
//             2. the name of a data unit
//             3. the specific parameter to be checked (default=listVisDef)
//
// -- OUTPUT : Yes - The VisDef is accepted for that data unit
//             No -  The VisDef does not match the data unit
bool ObjectList::CheckValidVisDef(const char* duClass, const char* vdClass, const char* vdPar)
{
    require(duClass != nullptr);
    require(vdClass != nullptr);

    // Retrieve the list of acceptable visdefs in the Object List
    const char* param = (vdPar) ? vdPar : "listVisDef";
    Cached listVisDef = Find("dataunit", duClass, param);

    // If no visdefs found, try the default key "listVisDef"
    if ((const char*)listVisDef == nullptr && vdPar)
        listVisDef = Find("dataunit", duClass, "listVisDef");

    ensure((const char*)listVisDef != nullptr);

    // Verify if the visDefClass belongs to the VisDefList
    return strstr((const char*)listVisDef, vdClass);
}

bool ObjectList::CheckValidVisDef(const char* duClass, const char* vdClass, int ndimFlag)
{
    require(duClass != nullptr);
    require(vdClass != nullptr);

    // Get visdef's key strings according to the input flag
    std::vector<std::string> vstr;
    VisDefNDimFlags(ndimFlag, vstr);

    // Check if visdef is valid
    // Use the default key string
    if (vstr.size() == 0 || vstr.size() > 1)
        return ObjectList::CheckValidVisDef(duClass, vdClass, "listVisDef");

    return ObjectList::CheckValidVisDef(duClass, vdClass, vstr[0].c_str());
}

#if 0
// MAYBE METVIEW 4 WILL NEED THIS FUNCTION IF IT STARTS HANDLING PTACH

// -- METHOD :  CheckValidVisDef
//
// -- PURPOSE:  Check if VisDef is valid using the Specific Valid Visdef
//              entry. If there is no such entry in the PlotModTable,
//              try to check in the Common Valid Visdef entry.
//              The reasons are that:
//              1) PGRIB accepts PWIND during the Drop process because
//                 PlotMod does not open the grib file to check if it
//                 contains any VECTOR_FIELD. This is done during the
//                 drawing process.
//              2) PlotMod does not have an icon of the type PTACH, so
//                 unfortunately there is an special treatment to deal 
//                 with PTACHs.
//
//  -- INPUT :  1. the visDef request
//              2. the name of a data unit
//
//  -- OUTPUT:  Yes - The VisDef is accepted for that data unit
//              No -  The VisDef does not match the data unit 
bool
ObjectList::CheckValidVisDef ( const char* dataunitClass, const MvRequest& request )
{
	require ( dataunitClass != 0 );

        // Check if visdef is of type PTACH
	const char* visdefClass;
	if ( ObjectList::IsVisDefIsotachs (request) )
		visdefClass =  PTACH;
	else
		visdefClass = request.getVerb();

	// Retrieve the list of acceptable visdefs in the Object List
	Cached listVisDef = Find ("dataunit", dataunitClass, "listSpecVisDef");
	if ( (const char*) listVisDef )
	{
		// Verify if visDefClass belongs to the VisDefList
		if ( strstr( (const char*)listVisDef, visdefClass ) )
			return true;
		else
			return false;
	}
	else
		return CheckValidVisDef(dataunitClass,visdefClass);
}
#endif

bool ObjectList::CheckValidVisDefList(const char* duClass, MvIconList& visdefList, const char* vdpar)
{
    MvIconList tmplist;
    MvIcon oneIcon;
    for (auto& jj : visdefList) {
        oneIcon = jj;
        if (ObjectList::CheckValidVisDef(duClass, oneIcon.Request().getVerb(), vdpar))
            tmplist.push_back(oneIcon);
    }

    visdefList = tmplist;

    return (visdefList.size() > 0) ? true : false;
}

void ObjectList::VisDefNDimFlags(int dimFlag, std::vector<std::string>& vstr)
{
    // No info about data dimension
    vstr.clear();
    if (dimFlag == 0)
        return;

    // Data contains 1-D data
    if (dimFlag & 1)
        vstr.emplace_back("1D_VISDEF");

    // Data contains 2D data
    if (dimFlag & 2)
        vstr.emplace_back("2D_VISDEF");
}


MvRequest
ObjectList::UserPreferencesRequest(const char* name)
{
    // Read the objectFileName in the METVIEW ObjectList
    MvRequest prefRequest;
    const char* requestFileName = Find("object", name)("default_name");

    // Get the filename full path
    std::string tt = MakeUserPrefPath(requestFileName);
    const char* filename = tt.c_str();

    // Do we have a preference ?
    if ((FileCanBeOpened(filename, "rw") == false) || (FileHasValidSize(filename) == false)) {
        // Try first to read the icon from the user Defaults directory.
        // If fails then creates a default version
        prefRequest = ObjectList::UserDefaultRequest(name);
        prefRequest.save(filename);
        return prefRequest;
    }

    prefRequest.read(filename);

    return prefRequest;
}

// -- METHOD :  UserDefaultRequest
//
// -- PURPOSE:  For each type of object, read a request
//              based on the user's default.
//              Parameter EXPAND equals true means that if the output request
//              contains any parameter, which is an icon (subrequest), then it
//              will be expanded
//
// -- INPUT  :  request name
//              flag indicating to expand all subrequests
//
// -- OUTPUT :  request
//
MvRequest
ObjectList::UserDefaultRequest(const char* requestName, bool expand)
{
    require(requestName != nullptr);

    // Read the objectFileName in the METVIEW ObjectList
    const char* requestFileName = Find("object", requestName)("default_name");
    ensure(requestFileName != nullptr);

    // Determine  the default path for the icon
    // Find the file which contains the request
    std::string fullName = MakeUserDefPath(requestFileName);
    std::string path = mdirname(fullName.c_str());

    // Create a new request and read its contents
    // for the file in the default directory
    MvRequest defaultRequest;
    if (FileCanBeOpened(fullName.c_str(), "r") == true) {
        defaultRequest.read(fullName.c_str(), expand);
        if (defaultRequest.countParameters() == 0)
            defaultRequest = ObjectList::CreateDefaultRequest(requestName, 0, path.c_str());

        if (!(const char*)defaultRequest("_NAME"))
            defaultRequest("_NAME") = fullName.c_str();

        if (!(const char*)defaultRequest("_CLASS"))
            defaultRequest("_CLASS") = requestName;
    }
    else
        defaultRequest = ObjectList::CreateDefaultRequest(requestName, 0, path.c_str());

    return defaultRequest;
}

// -- METHOD :  ExpandRequest
//
// -- PURPOSE:  Expand the request according to the Metview definition
//              and rules
//
// -- INPUT  :  Request, expansion flag
//
// -- OUTPUT :  Expanded request
MvRequest
ObjectList::ExpandRequest(const MvRequest& reqst, long expandFlag)
{
    // Expand the request against the METVIEW definition file
    MvRequest objectDef = Find("object", reqst.getVerb());
    Cached rulesFileName = objectDef("rules_file");
    Cached defFileName = objectDef("definition_file");

    if (expandFlag == 0)
        expandFlag = objectDef("expand");

    MvLanguage langMetview((const char*)defFileName,
                           (const char*)rulesFileName,
                           expandFlag);

    return langMetview.expandOne(reqst);
}

// -- METHOD :  CreateDefaultRequest
//
// -- PURPOSE:
//
// -- INPUT  :
//
// -- OUTPUT :

MvRequest
ObjectList::CreateDefaultRequest(const char* requestName, int expandFlag, const char* path)
{
    MvRequest request(requestName);
    MvRequest expRequest = ObjectList::ExpandRequest(request, expandFlag);

    // Add hidden parameters
    expRequest("_CLASS") = requestName;
    expRequest("_DEFAULT") = true;

    // Add parameter _NAME, including the path if it is given
    const char* name = (const char*)Find("object", requestName)("default_name");
    std::string defName;
    if (name) {
        defName = "<";
        defName += name;
        defName += ">";
    }
    else
        defName = "<default>";

    if (path) {
        std::string relName = path + std::string("/") + defName;
        expRequest("_NAME") = relName.c_str();
    }
    else
        expRequest("_NAME") = defName.c_str();

    return expRequest;
}

// -- METHOD :
//
// -- PURPOSE:
//
// -- INPUT  :
//
// -- OUTPUT :
bool ObjectList::IsDataUnit(const Cached& requestVerb)
{
    if (!requestVerb)
        return false;

    MvRequest objectDef = Find("dataunit", requestVerb);

    return objectDef("class") == requestVerb;
}

// -- METHOD :
//
// -- PURPOSE:
//
// -- INPUT  :
//
// -- OUTPUT :
bool ObjectList::IsWindow(const Cached& requestVerb)
{
    if (!requestVerb)
        return false;

    MvRequest objectDef = Find("window", requestVerb);

    return objectDef("class") == requestVerb;
}

// -- METHOD :
//
// -- PURPOSE:
//
// -- INPUT  :
//
// -- OUTPUT :
bool ObjectList::IsView(const Cached& requestVerb)
{
    if (!requestVerb)
        return false;

    MvRequest objectDef = Find("view", requestVerb);

    return objectDef("class") == requestVerb;
}

bool ObjectList::IsGeographicalView(const std::string& verb)
{
    if (verb.empty())
        return false;

    // Find viewname in the registered view list
    MvRequest objectDef = Find("view", verb.c_str());

    // Check if this is a geographical view
    std::string class1 = (const char*)objectDef("class");
    return (!class1.empty() && (class1 == GEOVIEW || class1 == MAPVIEW));
}

// -- METHOD :
//
// -- PURPOSE:
//
// -- INPUT  :
//
// -- OUTPUT :
bool ObjectList::IsVisDef(const Cached& requestVerb)
{
    if (!requestVerb)
        return false;

    MvRequest objectDef = Find("visdef", requestVerb);

    return objectDef("class") == requestVerb;
}

// -- METHOD :  IsVisDefContour
//
// -- PURPOSE:  Indicate if the request is a contouring request
//
// -- INPUT  :  Request verb
//
// -- OUTPUT :  true/false

bool ObjectList::IsVisDefContour(const char* verb)
{
    return (verb == MCONT || verb == PCONT);
}

// -- PURPOSE: Indicate if the request is a PTACH visdef
//
// -- INPUT  : Request
//
// -- OUTPUT : true/false
bool ObjectList::IsVisDefIsotachs(const MvRequest& request)
{
    // If it is PCONT, then check for Data_transformation
    if (IsVisDefContour(request.getVerb())) {
        const char* data = (const char*)request("CONTOUR_DATA_TRANSFORMATION");
        if (!data)  // no information about data_transformation
            return false;

        if (strcmp(data, ISOTACHS) == 0)
            return true;
        else
            return false;
    }

    return false;
}

// -- METHOD :  IsVisDefCoastlines
//
// -- PURPOSE:  Indicate if the request is a coastline request
//
// -- INPUT  :  Request verb
//
// -- OUTPUT :  true/false

bool ObjectList::IsVisDefCoastlines(const Cached& requestVerb)
{
    return (requestVerb == MCOAST || requestVerb == PCOAST);
}

bool ObjectList::IsVisDefText(const char* requestVerb)
{
    return (requestVerb == MTEXT || requestVerb == PTEXT);
}

bool ObjectList::IsVisDefTextTitle(const MvRequest& request)
{
    // Check if it is a Text icon
    const char* verb = request.getVerb();
    if (!IsVisDefText(verb))
        return false;

    // Check if it is a Text title
    if ((const char*)request("TEXT_MODE") &&
        ((const char*)request("TEXT_MODE") == std::string("POSITIONAL")))
        return false;

    return true;
}

bool ObjectList::IsVisDefTextAnnotation(const MvRequest& request)
{
    // Check if it is a Text icon
    const char* verb = request.getVerb();
    if (!IsVisDefText(verb))
        return false;

    // Check if it is a Text annotation
    if ((const char*)request("TEXT_MODE") &&
        ((const char*)request("TEXT_MODE") == std::string("POSITIONAL")))
        return true;

    return false;
}

bool ObjectList::IsVisDefLegend(const char* requestVerb)
{
    return (requestVerb == MLEGEND);
}

bool ObjectList::IsVisDefImport(const char* requestVerb)
{
    return (requestVerb == MIMPORT);
}

// -- METHOD :  IsAxis
//
// -- PURPOSE:  Indicate if the request is a PAXIS request
//
// -- INPUT  :  Request verb
//
// -- OUTPUT :  true/false
bool ObjectList::IsVisDefAxis(const Cached& requestVerb)
{
    return (requestVerb == MAXIS || requestVerb == PAXIS);
}

bool ObjectList::IsVisDefGraph(const Cached& requestVerb)
{
    return (requestVerb == MGRAPH || requestVerb == PGRAPH);
}

bool ObjectList::IsLayer(const char* verb)
{
    return (strcmp(verb, "LAYER") == 0 || strcmp(verb, "layer") == 0);
}

bool ObjectList::IsWeatherSymbol(const Cached& requestVerb)
{
    return strncmp((const char*)requestVerb, "WS_", 3) == 0;
}

// -- METHOD :  MacroName
//
// -- PURPOSE:  Find the macro name associated to a METVIEW object
//
// -- INPUT  :  The Object's class
//
// -- OUTPUT :  The macro name associated to the object
Cached
ObjectList::MacroName(const Cached& iconClass)
{
    Cached retVal = Find("object", iconClass, "macro");
    if (!retVal)
        retVal = iconClass;

    return retVal;
}

// -- METHOD :  CalledFromMacro
//
// -- PURPOSE:  Indicate if the request has been called from a macro
//
// -- INPUT  :  A request
//
// -- OUTPUT :  true/false
bool ObjectList::CalledFromMacro(const MvRequest& request)
{
    int i = request("_CALLED_FROM_MACRO");
    if (i == 1 || ((const char*)request("_APPL") &&
                   strcmp((const char*)request("_APPL"), "macro") == 0))
        return true;

    return false;
}

// -- METHOD :  GetCompanion
//
// -- PURPOSE:  Return the expected parameter to make a pair in a vector field.
//              ex. U/V, D/T... and the correspondent wind mode
//
// -- INPUT  :  param: parameter name
//
// -- OUTPUT :  pair : pair name ("no_pair" for scalar data)
//              mode : wind mode plotting
//              first: true - if there is a companion and the input parameter
//                            is the primarely/first element, i.e. it is not
//                            the friend element
void ObjectList::GetCompanion(const std::string& param, std::string& pair, std::string& mode, bool& first)
{
    MvRequest& objectList = ObjectList::Instance();
    objectList.rewind();

    std::string comp("companion");
    while (objectList) {
        if (objectList.getVerb() == comp) {
            if ((const char*)objectList("class") == param) {
                pair = (const char*)objectList("friend");
                mode = (const char*)objectList("mode") ? (const char*)objectList("mode") : "";
                first = true;
                return;
            }
            else if ((const char*)objectList("friend") == param) {
                pair = (const char*)objectList("class");
                mode = (const char*)objectList("mode") ? (const char*)objectList("mode") : "";
                first = false;
                return;
            }
        }
        objectList.advance();
    }

    pair = "no_pair";
    mode = "";
    first = false;
    return;
}

// Check if two variables are companions
bool ObjectList::AreCompanions(const std::string& pair1, const std::string& pair2)
{
    // Get the object list
    MvRequest& objectList = ObjectList::Instance();
    objectList.rewind();

    // Loop the list doing the checking
    std::string comp("companion");
    while (objectList) {
        if (objectList.getVerb() == comp && ((((const char*)objectList("class") == pair1) && ((const char*)objectList("friend") == pair2)) ||
                                             (((const char*)objectList("class") == pair2) && ((const char*)objectList("friend") == pair1))))
            return true;

        objectList.advance();
    }

    return false;
}

// -- METHOD :  IsImage
//
// -- PURPOSE:  Return true if the input representation is space view ("SV").
//
// -- REVISION (2014-09-02) : now we always return false because at least for
//                            now we don't want or need to distinguish between
//                            satellite and non-satellite GRIB fields.

bool ObjectList::IsImage(const char* /*repres*/)
{
    //(repres != nullptr && !strcmp(repres, "SV"));
    return false;
}

bool ObjectList::IsService(const char* classe, const char* action, bool context)
{
    MvRequest req = FindReqService(classe, action);
    if (!req)
        return false;

    if (context && !(int)req("context"))
        return false;

    return true;
}

bool ObjectList::IsDefaultValue(MvRequest& in, const char* param)
{
    bool retVal = false;

    MvRequest defReq = CreateDefaultRequest(in.getVerb());

    if (metview::IsParameterSet(in, param) && metview::IsParameterSet(defReq, param)) {
        if (is_number(in(param)) && is_number(defReq(param)))
            retVal = ((double)in(param) == (double)defReq(param));
        else
            retVal = (strcmp(in(param), defReq(param)) == 0);
    }

    return retVal;
}

bool ObjectList::IsThermoView(const char* verb)
{
    return (verb == THERMOVIEW);
}

bool ObjectList::IsThermoGrid(const char* verb)
{
    return (verb == MTHERMOGRID);
}

bool ObjectList::IsTaylorGrid(const char* verb)
{
    return (verb == MTAYLORGRID);
}
