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

// Methods for class AverageView
//
// This is the exemplar object for the AverageView class
// 
//
#include "AverageView.h"
#include <MvRequestUtil.hpp>
#include "ObjectList.h"
#include "PlotMod.h"
#include "Root.h"

//--------------------------------------------------------
static AverageViewFactory averageViewFactoryInstance;

PlotModView*
AverageViewFactory::Build ( Page& page,
                            const MvRequest& contextRequest,
                            const MvRequest& setupRequest )
{
   // Instantiate a Average view
   return new AverageView ( page, contextRequest, setupRequest );
}

//--------------------------------------------------------
static AverageViewM3Factory averageView3FactoryInstance;

PlotModView*
AverageViewM3Factory::Build ( Page& page,
                             const MvRequest& contextRequest,
                             const MvRequest& setupRequest )
{
   // Translate view request to Metview 4
   MvRequest viewM4Req = this->Translate(contextRequest);

   // Instantiate a Average view
   return new AverageView ( page, viewM4Req, setupRequest );
}

MvRequest
AverageViewM3Factory::Translate ( const MvRequest& in )
{
   // Send a warning message
   PlotMod::Instance().MetviewError ("The Metview 3 AVERAGE VIEW icon is deprecated. An automatic translation to the Metview 4 AVERAGE VIEW icon will be performed internally, but may not work for all cases. It is recommended to manually replace the old icons with their new equivalents.","WARNING");

   // Expand request
   MvRequest req = ObjectList::ExpandRequest(in,EXPAND_DEFAULTS);

   // Copy Area and Direction parameters
   MvRequest viewReq("MXAVERAGEVIEW");
   viewReq.addValue("AREA",(double)req("AREA",0));
   viewReq.addValue("AREA",(double)req("AREA",1));
   viewReq.addValue("AREA",(double)req("AREA",2));
   viewReq.addValue("AREA",(double)req("AREA",3));
   viewReq("DIRECTION") = req("DIRECTION");

   // Translate Levels interval
   viewReq("BOTTOM_LEVEL") = (double)req("BOTTOM_PRESSURE");
   viewReq("TOP_LEVEL")    = (double)req("TOP_PRESSURE");

   // Translate Vertical scaling parameter
   viewReq("VERTICAL_SCALING") = (const char*)req("PRESSURE_LEVEL_AXIS");

   // Overlay Control parameter is not translated
   PlotMod::Instance().MetviewError ("The Metview 3 AVERAGE VIEW icon is deprecated. Parameter OVERLAY CONTROL will not be internally translated.\n","WARNING");

   // Copy Page and Subpage parameters
   CopySomeParameters ( req,viewReq,"Subpage");
   CopySomeParameters ( req,viewReq,"Page");

   // Expand output request
   MvRequest out = ObjectList::ExpandRequest(viewReq,EXPAND_DEFAULTS);

   return out;
}

//------------------------------------------------------------

AverageView::AverageView ( Page& owner,
                           const MvRequest& viewRequest,
                           const MvRequest& setupRequest ): 
             CommonXSectView ( owner, viewRequest, setupRequest ),
             yReverse_("off")
{
    ApplicationName("MXAVERAGE");
    SetVariables(viewRequest,true);
}

AverageView::AverageView (const AverageView &old) :
             CommonXSectView(old),
             axisType_(old.axisType_),
             yReverse_(old.yReverse_)
{
}

string AverageView::Name()
{
    int id = Owner().Id();
    string name =  (const char*)ObjectInfo::ObjectName ( viewRequest_, "AverageView", id );

    return name ;
}

void 
AverageView::DescribeYourself ( ObjectInfo& description )
{
    // Convert my request to macro
    set<Cached> skipSet;
    description.ConvertRequestToMacro ( appViewReq_, PUT_END,
                                        MacroName().c_str(),"maverageview", skipSet);

    description.PutNewLine (" " );
}

// In request is either a new viewrequest, or a data info request.
void AverageView::SetVariables(const MvRequest &in, bool resetMembers)
{
    // Called with a viewRequest
    if ( resetMembers )
    {
        latMin_ = in("AREA",0);
        latMax_ = in("AREA",2);
        lonMin_ = in("AREA",1);
        lonMax_ = in("AREA",3);

        if ( strcmp(in("DIRECTION"),"NS")  &&
             strcmp(in("DIRECTION"),"NORTH SOUTH") )
            axisType_ = "LATITUDE";
        else
            axisType_ = "LONGITUDE";
    }
    else // Called with a netCDF request.
    {
        viewRequest_.unsetParam("AREA");
        viewRequest_.addValue("AREA",(double)in("AREA",0));
        viewRequest_.addValue("AREA",(double)in("AREA",1));
        viewRequest_.addValue("AREA",(double)in("AREA",2));
        viewRequest_.addValue("AREA",(double)in("AREA",3));

        if  ( (const char*)in("MODE") && strcmp(in("MODE"),"AVERAGE_EW" ) == 0)
        {
            viewRequest_("DIRECTION") = "NS";
            axisType_ = "LONGITUDE";
        }
        else
        {
            viewRequest_("DIRECTION") = "EW";
            axisType_ = "LATITUDE";
        }
    }

    // Save some data specific to some DataApplication
    ApplicationInfo(in);
}

bool AverageView::UpdateView ()
{
    // It has already been updated
    if ( string(viewRequest_.getVerb()) == CARTESIANVIEW )
        return true;

    // Check where the axes min/max values should be taken from
    bool axisAuto = false;
    if ( (const char*)viewRequest_("_DEFAULT") &&
         (int)viewRequest_("_DEFAULT") == 1 &&
         (const char*)viewRequest_("_DATAATTACHED") &&
         strcmp((const char*)viewRequest_("_DATAATTACHED"),"YES") == 0
       )
          axisAuto = true;

    // Translate X coordinates
    MvRequest cartView("CARTESIANVIEW");
    if ( axisAuto )
       cartView("X_AUTOMATIC") = "on";
    else
    {
       cartView("X_AUTOMATIC") = "off";
       if ( axisType_ == "LATITUDE" )
       {
          cartView("X_MIN") = latMin_;
          cartView("X_MAX") = latMax_;
       }
       else
       {
          cartView("X_MIN") = lonMin_;
          cartView("X_MAX") = lonMax_;
       }
    }
    cartView("X_AXIS_TYPE") = axisType_.c_str();

    // Translate Y coordinates
    if ( axisAuto )
    {
       cartView("Y_AUTOMATIC") = "on";
       cartView("Y_AUTOMATIC_REVERSE") = yReverse_.c_str();
    }
    else
    {
       cartView("Y_AUTOMATIC") = "off";
       cartView("Y_MIN")       = yMin_;
       cartView("Y_MAX")       = yMax_;
    }

    const char* log = viewRequest_("VERTICAL_SCALING");
    if ( log && strcmp(log,"LOG") == 0)
        cartView("Y_AXIS_TYPE") = "logarithmic";
    else
        cartView("Y_AXIS_TYPE") = "regular";


    // Copy axis definition
    cartView.setValue("HORIZONTAL_AXIS",viewRequest_.getSubrequest("HORIZONTAL_AXIS"));
    cartView.setValue("VERTICAL_AXIS",viewRequest_.getSubrequest("VERTICAL_AXIS"));

    // Copy PAGE and SUBPAGE definition
    CopySomeParameters( viewRequest_,cartView,"PAGE" );
    CopySomeParameters( viewRequest_,cartView,"SUBPAGE" );

    // Copy the original request without certain parameteres (to avoid duplication)
    RemoveParameters( viewRequest_, "HORIZONTAL_AXIS" );
    RemoveParameters( viewRequest_, "VERTICAL_AXIS" );
    RemoveParameters( viewRequest_, "PAGE" );
    RemoveParameters( viewRequest_, "SUBPAGE" );
    RemoveParameters( viewRequest_, "_" );
    cartView("_ORIGINAL_REQUEST") = viewRequest_;

    // Update request
    viewRequest_ = cartView;;

    // Indicate that the plotting tree needs to be rebuilt
    Root::Instance().Refresh(false);

    return true;
}

void AverageView::ApplicationInfo ( const MvRequest& req )
{
   // Save direction of the vertical axis
   if ( (const char*)req("Y_AUTOMATIC_REVERSE") )
      yReverse_ = (const char*)req("Y_AUTOMATIC_REVERSE");
   else if ( (const char*)req("_Y_AUTOMATIC_REVERSE") )
      yReverse_ = (const char*)req("_Y_AUTOMATIC_REVERSE");
}

bool AverageView::ConsistencyCheck( MvRequest& req1, MvRequest& req2 )
{
   // Build a list of parameters to be checked
   vector<string> params;
   params.push_back("AREA");
   params.push_back("DIRECTION");

   // Expand requests using the same expansion flag to avoid
   // problems with parameters with multiple values (e.g.
   // NS or NORTH_SOUTH are valid values for parameter DIRECTION
   MvRequest t1 = ObjectList::ExpandRequest(req1,EXPAND_DEFAULTS);
   MvRequest t2 = ObjectList::ExpandRequest(req2,EXPAND_DEFAULTS);

   // Call a function to perform the consistency check
   return t1.checkParameters(t2,params);
}
