/***************************** 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 <MvRequestUtil.hpp>
#include <Assertions.hpp>

#include "DataObject.h"
#include "DrawingPriority.h"
#include "GraphicsEngine.h"
#include "MvLayer.h"
#include "ObjectList.h"
#include "PlotMod.h"
#include "MvLog.h"

DataObject::DataObject(int dataUnitId, long offset, long offset2,
                       const MvRequest& dataInfo) :
    Presentable(dataInfo),
    myDataUnitId_(dataUnitId),
    dimFlag_(0)
{
    // Set the verb, default is GRIB
    const char* dt = dataInfo("DATA_TYPE");
    if (dt)
        myRequest_.setVerb(dt);
    else {
        myRequest_.setVerb("GRIB");
        return;
    }

    // Add dimension and position information.
    // If the second index is not equal to the first one,
    // this data is a 2D field.
    // FAMI 022017: at the moment, dimension info is only related to
    // GRIB and GEOPOINTS data. Review this code if this condition changes.
    if (strcmp(dt, "GEOPOINTS") == 0) {
        if ((const char*)dataInfo("_NDIM_FLAG"))
            dimFlag_ = (int)dataInfo("_NDIM_FLAG");

        return;
    }
    else if (strcmp(dt, "GRIB") == 0) {
        int ndim = 1;
        myRequest_("GRIB_POSITION") = offset;
        if (offset != offset2) {
            ndim = 2;
            myRequest_("GRIB_POSITION") += offset2;
            if ((const char*)dataInfo("WIND_MODE"))
                myRequest_("GRIB_WIND_MODE") = (const char*)dataInfo("WIND_MODE");
        }

        myRequest_("GRIB_DIMENSION") = ndim;
        dimFlag_ = dimFlag_ | ndim;
    }
}

DataObject::DataObject(MvRequest& reqst) :
    Presentable(reqst)
{
    // empty
}

DataObject::DataObject(const DataObject& old) :
    Presentable(old),
    myDataUnitId_(old.myDataUnitId_),
    dimFlag_(0),
    legends_(old.legends_),
    titleText_(old.titleText_),
    titleRequest_(old.titleRequest_)
{
    // segmentNameMap_ not copied.
}

bool DataObject::AppendDataUnit(int dataunitId, long offset, long offset2, const MvRequest& req)
{
    // Do not append if this is a new data
    if (!this->Match(dataunitId, req))
        return false;

    // Update position and dimension parameters
    int ndim = 1;
    myRequest_("GRIB_POSITION") += offset;
    if (offset != offset2)  // two dimensional data
    {
        ndim = 2;
        myRequest_("GRIB_POSITION") += offset2;
    }

    myRequest_("GRIB_DIMENSION") += ndim;
    dimFlag_ = dimFlag_ | ndim;

    return true;
}

// Check if the current data and new data match
// True -> they match, False-> they do not match
bool DataObject::Match(int dataunitId, const MvRequest& req)
{
    // New data and current data are not from the same file -> return false
    if (myDataUnitId_ != dataunitId)
        return false;

    // The request verbs are not the same -> return false
    if (strcmp(myRequest_.getVerb(), req("DATA_TYPE")) != 0)
        return false;

    return true;
}

DrawPriorMap
DataObject::DrawPriority(MvIconList& visdefList)
{
    DrawPriorMap drawPriorMap;

    // Each data unit has a unique identifier - which is
    // the key to retrieve it
    require(myDataUnitId_ > 0);

    // Get DrawingPriority from Page
    DrawingPriority& tmpDrawingPriority = this->GetDrawPriority();

    // Create Priority string based on only the first visdef.
    // It assumes that all the other visdefs will have the same "priority"
    MvListCursor vdCursor;
    vdCursor = visdefList.begin();
    MvIcon& visDef = *(vdCursor);
    MvRequest visRequest = visDef.Request();

    int visDefId = visDef.Id();
    Cached drawPrior = tmpDrawingPriority.DrawSegmentName(myDataUnitId_,
                                                          visRequest,
                                                          visDefId);
    std::string dataString((const char*)drawPrior);
    pair<int, int> tmpPair(this->Id(), visDefId);
    drawPriorMap[dataString] = tmpPair;

    return drawPriorMap;
}

DrawPriorMap
DataObject::DrawPriority()
{
    // Each data unit has a unique identifier - which is
    // the key to retrieve it
    require(myDataUnitId_ > 0);

    // Retrieve the Icon Data Base
    MvIconDataBase& dataBase = IconDataBase();

    // Retrieve the DataUnit
    // (the object only stores its dataunit Id and index)
    MvIcon dataUnit;
    // if ( dataBase.RetrieveDataUnit (myDataUnitId_, dataUnit) == false)
    if (dataBase.RetrieveIconFromList(DB_DATAUNIT, myDataUnitId_, dataUnit) == false)
        return {};

    // Retrieve the VisDefs associated to the DataUnit
    MvIconList visdefList;
    RetrieveMyVisDefList(dataUnit, visdefList);

    return DrawPriority(visdefList);
}

#if 0
// Don't attempt to get visdefs, they're given as input
void DataObject::DrawVisDef(MvIcon& visDef, std::string& /* segmentName */)
{
  // Retrieve the Graphics Engine
  GraphicsEngine& ge = this->GetGraphicsEngine();

  MvIconDataBase&   dataBase = IconDataBase();

  MvIcon  dataUnit;
  if ( dataBase.RetrieveDataUnit (myDataUnitId_, dataUnit) == false)
    {
      COUT << "DataObject::Draw() -> No Data Unit" << std::endl;
      return;
    }

//D  segmentNameMap_[visDef.Id()] = segmentName;

  // Call the graphics Engine
  ge.Draw ( dataUnit, myRequest_, visDef, this->GetCanvas() );
}
#endif

void DataObject::DrawDataVisDef()
{
    // Retrieve the Graphics Engine and the data base info
    GraphicsEngine& ge = GetGraphicsEngine();
    MvIconDataBase& dataBase = IconDataBase();

    // Retrieve the DataUnit
    MvIcon dataUnit;
    if (dataBase.RetrieveIconFromList(DB_DATAUNIT, myDataUnitId_, dataUnit) == false) {
        MvLog().popup().err() << "uPlot DataObject::DrawDataVisDef-> No Data Unit";
        return;
    }

    // Retrieve all VisDefs associated to the DataUnit
    MvIconList visdefList;
    bool defaultVD = RetrieveMyVisDefList(dataUnit, visdefList);

    // Update DataBase if this is the first plot (i.e. not a result of a dropping
    // icon) with the NDimensional flag. This could not be done earlier, during
    // the Drop procedure, because this information is only available after
    // having decoded the whole DataObject and the task of inserting the DataObject
    // to the DataBase was done earlier.
    //   bool first = false;;
    MvRequest dataRequest = dataUnit.Request();
    if (!(const char*)dataRequest("_NDIM_FLAG")) {
        dataRequest("_NDIM_FLAG") = dimFlag_;
        dataBase.UpdateIcon(DB_DATAUNIT, dataUnit.Id(), dataRequest);
        //      first = true;
    }

    // Call the Graphics Engine to store the Layer info.
    DrawLayerInfo(dataUnit.Id());

    // Call the Graphics Engine to store the Data and Visdef info.
    ge.DrawDataVisDef(dataUnit, myRequest_, visdefList, dimFlag_);

    // Update DataBase if this is the first plot and the visdefList is a default one.
    // If visdefList is not a default one, this means that the DataBase was already
    // updated earlier.
    // In the first plot, before calling ge.Draw, the list of visdefs contains
    // all valid visdefs. After calling ge.Draw, it contains only the visdefs
    // used in the plotting. If this is not the first plot, the Drop scheme (executed
    // earlier) should update (add/replace/delete) the list of visdefs accordingly.
    // F   if ( first && defaultVD )
    if (defaultVD) {
        // Insert new VD in the dataBase connect to the superpage
        int spId = this->FindSuperPage()->Id();
        MvListCursor iCursor;
        for (iCursor = visdefList.begin(); iCursor != visdefList.end(); ++iCursor) {
            //         dataBase.InsertVisDef ( *iCursor, myDataUnitId_, dataUnit);
            dataBase.InsertIcon(PRES_VISDEF_REL, spId, *iCursor);
        }
    }
}

#if 0
// EraseDraw - 
// Erase data object drawing on canvas
// If visDefId is zero, all drawing of this DataObject should be
//	removed
void 
DataObject::EraseDraw( int visDefId )
{
  require (myDataUnitId_ > 0);
  
  // Retrieve the canvas
  Canvas& canvas = this->GetCanvas();
  
  // Erase all pairs
  SegmentNameMap::iterator ii;
  for ( ii = segmentNameMap_.begin(); ii != segmentNameMap_.end(); ++ii )
    {

      int visId = (*ii).first; 
      if ( visDefId && (visDefId != visId ) ) continue;
      
      std::string dataString = (*ii).second;
      
//D      if ( canvas.RemoveForAll(myParent_->Id(),dataString) ) 
	{
	  this->RemoveLegend ( dataString );
	  myParent_->NeedsRedrawing ( true );
	}
    }
}

void 
DataObject::EraseDefaultDraw ()
{
	EraseDraw();
}
#endif

bool DataObject::RetrieveMyVisDefList(MvIcon& dataUnit, MvIconList& visdefList)
{
    bool usingDefault = false;

    // Retrieve the Icon Data Base
    MvIconDataBase& dataBase = IconDataBase();

    // Retrieve the VisDefs associated to the DataUnit
    if (dataBase.RetrieveVisDefList(dataUnit, visdefList)) {
        // Check if there is any valid visdef
        if (ObjectList::CheckValidVisDefList(myRequest_.getVerb(), visdefList))
            return usingDefault;  // found a valid visdef
    }

    // Check if there is a parent DataUnit
    int parentDataUnitId = dataUnit.ParentId();
    if (parentDataUnitId) {
        // There is a parent, look for its Visdefs
        MvIcon parentDataUnit;
        dataBase.RetrieveIconFromList(DB_DATAUNIT, parentDataUnitId, parentDataUnit);
        dataBase.RetrieveVisDefList(parentDataUnit, visdefList);

        // Check that the parent has a valid visdef for this dataunit
        if (ObjectList::CheckValidVisDefList(myRequest_.getVerb(), visdefList))
            return usingDefault;  // found a valid visdef
    }

    // There is no visdef associated to the dataunit -> get another visdef
    // (it could be either in the Page, SuperPage or in the Root).
    // If the dataunit has a flag indicating a specific visdef then apply (A);
    // otherwise, (B).

    // (A) Verify if the dataunit suggests an specific visdef
    MvRequest reqAux = dataUnit.Request();
    if ((const char*)reqAux("_VISDEF")) {
        usingDefault = this->DefaultVisDefList((const char*)reqAux("_VISDEF"), visdefList, dimFlag_, GETBYVISDEF);
    }
    else {
        // (B) Find a suitable visdef throughout the Presentable tree.
        // Retrieve a default visdef if nothing was found.
        usingDefault = this->DefaultVisDefList(myRequest_.getVerb(), visdefList, dimFlag_);
    }

    // If it is a default visdef, update some parameters
    if (usingDefault)
        this->UpdateVisDef(reqAux, visdefList);

    return usingDefault;
}

#if 0
void
DataObject::SetTitle ( const MvRequest& treq )
{
	MvRequest rqst = treq;

	// Should have only one package, use the latest
	int nPacks  = rqst ( "$METVIEW_TITLE_PACKAGE_COUNT" );
	Cached titlePackageName = "$METVIEW_TITLE_PACKAGE_";
	titlePackageName = titlePackageName + nPacks;

	int nValues = rqst.countValues ( titlePackageName );
	if ( nValues )
	{
		titleText_.resize ( nValues );

		for ( int i = 0; i < nValues; i++ )
			titleText_ [i] = rqst ( titlePackageName, i );

		// Save Text information related to Grib ('GRIB_TEXT_...')
		MvRequest auxReq = rqst.getSubrequest("$METVIEW_TITLE_PACKAGE_1_REQUEST");
                titleRequest_ = empty_request(nullptr); 
                CopySomeParameters (auxReq,titleRequest_,"GRIB_TEXT");
	}
	else if ( IsParameterSet ( rqst, "TEXT_LINE_1" ) )
	{
		if ( IsParameterSet ( rqst, "TEXT_LINE_COUNT" ) )
			CopySomeParameters ( rqst, myRequest_, "TEXT_LINE_" );
		else
		{
			myRequest_ ( "TEXT_LINE_1" ) = (const char*)rqst ( "TEXT_LINE_1" );
			myRequest_.unsetParam ( "TEXT_LINE_COUNT" );
		}
	}
}
#endif

void DataObject::GetTitle(MvRequest& rqst, int* order)
{
    int i = 0;

    // Set TEXT_ORIGIN, internal parameter between PlotMod and Magics
    this->SetTextOrigin(rqst);

    char name[50];
    sprintf(name, "TEXT_LINE_%d", *order);

    int nValues = titleText_.size();
    if (nValues)  // There is an automatic title package
    {
        rqst("$METVIEW_TITLE_PACKAGE_COUNT") = *order;

        Cached titlePackageName = "$METVIEW_TITLE_PACKAGE_";
        titlePackageName = titlePackageName + *order;

        rqst(titlePackageName) = titleText_[0];
        for (i = 1; i < nValues; i++)
            rqst(titlePackageName) += titleText_[i];

        // Add title information related to the Grib ('GRIB_TEXT_...')
        metview::CopySomeParameters(titleRequest_, rqst, "GRIB_TEXT");

        (*order)++;
    }
    else  // Title defined by the user
    {
        // Merge 2 TEXT requests
        const char* origin = rqst("TEXT_ORIGIN");
        if (origin == Cached("AUTOMATIC")) {
            // Clear user TEXT_LINE_*
            char saux[13];
            strcpy(saux, "TEXT_LINE_");
            int size = strlen(saux);
            int j = myRequest_("TEXT_LINE_COUNT");
            rqst.unsetParam("TEXT_LINE_COUNT");
            for (i = 1; i <= j; i++) {
                sprintf(saux + size, "%d", i);
                rqst.unsetParam(saux);
            }

            // Copy TEXT parameters
            metview::CopySomeParameters(myRequest_, rqst, "TEXT_", (bool)false);
        }
        else if (origin == Cached("BOTH") || origin == Cached("MERGE"))
            metview::MergeTextParameters(myRequest_, rqst, false);

        /// F		( *order ) = rqst("TEXT_LINE_COUNT");

        // Now we have already set the Text request.
        // For the Magics point of view, if the title came from
        // an  Application which produces its own title (p.e.,
        // XSection), it is necessary to reset TEXT_ORIGIN
        // to USER.
        if (!this->MagicsTitle())
            rqst("TEXT_ORIGIN") = Cached("USER");
    }
}

void DataObject::SetTextOrigin(MvRequest& request)
{
    // If TEXT_ORIGIN has already been set, return.
    if (metview::IsParameterSet(request, "TEXT_ORIGIN")) {
        std::string val = (const char*)request("TEXT_ORIGIN");
        if (val != "NOTSET")
            return;
    }

    // Check if TEXT_AUTOMATIC, TEXT_USER and TEXT_MERGE has
    // been set (these are PlotMod parameters and
    // must not be sent to Magics)
    MvRequest reqAux = request;
    bool expand = false;
    if (metview::IsParameterSet(reqAux, "TEXT_AUTOMATIC"))
        request.unsetParam("TEXT_AUTOMATIC");
    else
        expand = true;

    if (metview::IsParameterSet(reqAux, "TEXT_USER"))
        request.unsetParam("TEXT_USER");
    else
        expand = true;

    if (metview::IsParameterSet(reqAux, "TEXT_MERGE"))
        request.unsetParam("TEXT_MERGE");
    else
        expand = true;

    // Expand request in order to retrieve the default values
    if (expand)
        reqAux = ObjectList::ExpandRequest(reqAux, EXPAND_DEFAULTS);

    // Set TEXT_ORIGIN
    Cached yes("YES");
    bool autoText = (reqAux("TEXT_AUTOMATIC") == yes) ? true : false;
    bool userText = (reqAux("TEXT_USER") == yes) ? true : false;
    bool mergeText = (reqAux("TEXT_MERGE") == yes) ? true : false;

    if (mergeText)
        request("TEXT_ORIGIN") = Cached("MERGE");
    else if (autoText && userText)
        request("TEXT_ORIGIN") = Cached("BOTH");
    else if (!autoText && userText)
        request("TEXT_ORIGIN") = Cached("USER");
    else if (autoText && !userText)
        request("TEXT_ORIGIN") = Cached("AUTOMATIC");
    else
        request("TEXT_ORIGIN") = Cached("NONE");

    // Set TEXT_LINE_COUNT. For MAGICS point of view the default
    // value is 1. However, for PLOTMOD this value must be set.
    int ncount = request("TEXT_LINE_COUNT");
    if (userText && ncount == 0)
        request("TEXT_LINE_COUNT") = 1;
}

#if 0
void
DataObject::SetLegend ( const MvRequest& rqst )
{
	// Should have only one package
	int nPackages = rqst ( "$METVIEW_LEGEND_PACKAGE_COUNT" );
	if ( nPackages == 1 )
	{
		Cached titlePackageName = Cached ( "$METVIEW_LEGEND_PACKAGE_" ) +
						   nPackages;
		int nValues = rqst.countValues ( titlePackageName );
		vector<int> values ( nValues );
		for ( int i = 0; i < nValues; i++ )
			 values [i] = rqst ( titlePackageName, i );

		Cached fileStoreName = Cached ( "METVIEW_LEGEND_STORE_FILE_" ) +
				       nPackages;
		Cached fileName = rqst ( fileStoreName );
        std::string name = (const char *) fileName;
        std::string typeName = (const char* ) rqst ("TYPE");
		legends_ [ typeName ] = LegendPackage ( name, values );
	}
}
#endif

bool DataObject::GetLegend(MvRequest& rqst, int* order)
{
    // Present Magics Limit
    if (*order > MAX_LEGENDS_PACKAGE)
        return false;

    if (legends_.size()) {
        for (auto& legend : legends_) {
            Cached titlePackageName = Cached("$METVIEW_LEGEND_PACKAGE_") +
                                      *order;
            rqst("$METVIEW_LEGEND_PACKAGE_COUNT") = *order;

            LegendPackage legendPackage = legend.second;

            rqst(titlePackageName) = (legendPackage.second)[0];
            for (unsigned int i = 1; i < (legendPackage.second).size(); i++)
                rqst(titlePackageName) += (legendPackage.second)[i];

            Cached fileName = Cached("METVIEW_LEGEND_STORE_FILE_") + *order;
            rqst(fileName) = (legendPackage.first).c_str();

            (*order)++;
            if (*order > MAX_LEGENDS_PACKAGE)
                return true;
        }
        return true;
    }

    return false;
}

#if 0
bool
DataObject::RemoveLegend ( std::string name )
{
	// Only one legend per data allowed
	legends_.clear ();
	
	LegendsMap::iterator i = legends_.find ( name );
	if ( i != legends_.end() )
	{
		legends_.erase ( i );
		return true;
	}
	return false;
}
 
MvRequest
DataObject::DataRequest ()
{
	MvRequest dataRequest;

	MvIconDataBase& dataBase = this->IconDataBase ();
	MvIcon dataUnitIcon;
	dataBase.RetrieveDataUnit ( myDataUnitId_, dataUnitIcon );
	const MvRequest dataunitRequest = dataUnitIcon.Request ();

	if ( Cached ( myRequest_.getVerb () ) == GRIB )
	{
		dataRequest = dataunitRequest;		
		dataRequest ( "OFFSET" ) = myDataIndex_;
		dataRequest ( "LENGTH" ) = 0;
	}
	else if ( Cached ( myRequest_.getVerb () ) == IMAGE )
	{
		dataRequest.setVerb ( "IMAGE" );
		dataRequest ( "PATH" ) = (const char*)dataunitRequest ( "PATH" ); 
		dataRequest ( "OFFSET" ) = myDataIndex_;
		dataRequest ( "LENGTH" ) = 0;
		const char* name = dataunitRequest("_NAME");
		if ( name )
		     dataRequest ( "_NAME" ) = name; 
	}
	else if ( Cached ( myRequest_.getVerb () ) == VECTOR_FIELD )
	{
		dataRequest.setVerb ( "VECTOR_FIELD" );
		MvRequest gribRequest = dataunitRequest;
		gribRequest ( "OFFSET" ) = myDataIndex_;
		gribRequest ( "LENGTH" ) = 0;
		dataRequest ( "U_COMPONENT" ) = gribRequest;

		gribRequest = dataunitRequest;
		gribRequest ( "OFFSET" ) = myDataIndex2_;
		gribRequest ( "LENGTH" ) = 0;
		dataRequest ( "V_COMPONENT" ) = gribRequest;
	}
	else
	{
		dataRequest = dataunitRequest;		
	}
	return dataRequest;
}			

// Overridden from Presentable. Although DataObject is a Presentable,
// it must be trated differently. It's got no children, and VisDefs
// are attached through it's dataunit id, not the presentable id.
void DataObject::DuplicateChildren(const Presentable& old)
{
  MvIconDataBase& dataBase = IconDataBase();
  MvIconDataBase& oldDB = old.IconDataBase(); 
  MvIcon visDef;
  
  // VisDefs
  oldDB.DataUnitVisDefRelationRewind();

  while ( oldDB.NextVisDefByDataUnitId(DataUnitId(),visDef) )
    dataBase.DataUnitVisDefRelation(DataUnitId(),visDef.Id() );
}
#endif

bool DataObject::MagicsTitle()
{
    const char* dataType = myRequest_("DATA_TYPE");
    if (dataType && (strcmp(dataType, "GRIB") == 0 ||
                     strcmp(dataType, "GEOPOINTS") == 0 ||
                     strcmp(dataType, "IMAGE") == 0 ||
                     strcmp(dataType, "BUFR") == 0))
        return true;
    else
        return false;
}

void DataObject::DataUnit(MvIcon& dataUnit)
{
    // Retrieve the data base info
    MvIconDataBase& dataBase = IconDataBase();

    // Retrieve the DataUnit
    // if (dataBase.RetrieveDataUnit (myDataUnitId_, dataUnit) == false)
    if (dataBase.RetrieveIconFromList(DB_DATAUNIT, myDataUnitId_, dataUnit) == false) {
        MvLog().popup().err() << "uPlot DataObject::DataUnit-> No Data Unit";
        return;
    }
}

// Update some visdef parameters only for the following cases:
// a) Scatter/GeoScatter applications and parameter "VALUES" is defined
//    and visdef is MSYMB
// b) Vector_Scatter/Geo_Vector_Scatter applications and parameter "VALUES"
//    is defined and visdef is MWIND
void DataObject::UpdateVisDef(MvRequest dataUnit, MvIconList& iconList)
{
    // Get application name without the prefix
    std::string verb = dataUnit.getVerb();
    size_t ipos = verb.find("_");
    std::string sapp = verb.substr(ipos + 1);
    std::string prefix = verb.substr(0, ipos);

    // Update visdef parameters only for the following applications
    if (sapp == "XY_POINTS" || sapp == "GEO_POINTS") {
        // Update only if parameter *_VALUES or *_VARIABLE_NAME is given
        std::string param1 = prefix + "_VALUES";
        std::string param2 = prefix + "_VARIABLE_NAME";
        std::string param2Sval;
        if ((const char*)dataUnit(param2.c_str()))
            param2Sval = (const char*)dataUnit(param2.c_str());

        if ((const char*)dataUnit(param1.c_str()) || param2Sval.size()) {
            // Update only MSYMB visdefs
            MvListCursor vdc;
            for (vdc = iconList.begin(); vdc != iconList.end(); ++vdc) {
                MvIcon& visDef = *(vdc);
                MvRequest vdRequest = visDef.Request();
                if (strcmp(vdRequest.getVerb(), "MSYMB") == 0) {
                    vdRequest("SYMBOL_TABLE_MODE") = "ADVANCED";
                    visDef.SaveRequest(vdRequest);
                }
            }
        }
    }
    else if (sapp == "XY_VECTORS" || sapp == "GEO_VECTORS") {
        // Update only if parameter *_VALUES or *_VARIABLE_NAME is given
        std::string param1 = prefix + "_VALUES";
        std::string param2 = prefix + "_VARIABLE_NAME";
        std::string param2Sval;
        if ((const char*)dataUnit(param2.c_str()))
            param2Sval = (const char*)dataUnit(param2.c_str());

        if ((const char*)dataUnit(param1.c_str()) || param2Sval.size()) {
            // Update only MWIND visdefs
            MvListCursor vdc;
            for (vdc = iconList.begin(); vdc != iconList.end(); ++vdc) {
                MvIcon& visDef = *(vdc);
                MvRequest vdRequest = visDef.Request();
                if (strcmp(vdRequest.getVerb(), "MWIND") == 0) {
                    vdRequest("WIND_ADVANCED_METHOD") = "ON";
                    visDef.SaveRequest(vdRequest);
                }
            }
        }
    }
    else if (sapp == "HOR_BAR" || sapp == "VER_BAR") {
        // Update MGRAPH visdefs
        MvListCursor vdc;
        for (vdc = iconList.begin(); vdc != iconList.end(); ++vdc) {
            MvIcon& visDef = *(vdc);
            MvRequest vdRequest = visDef.Request();
            if (strcmp(vdRequest.getVerb(), "MGRAPH") == 0) {
                vdRequest("GRAPH_TYPE") = "BAR";
                visDef.SaveRequest(vdRequest);
            }
        }
    }

    // Update database
    // It seems that this update is not need (keep an eye...)
}
