/***************************** 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 <MvApplication.h>
#include <MvRequestUtil.hpp>
#include "PlotMod.h"
#include "PlotModConst.h"
#include "MvStopWatch.h"

#include <assert.h>

// Methods for the PlotMod class
//
// --- METHOD:  Instance
//
// Methods to provide access to the singleton
//              PlotMod class 

PlotMod* PlotMod::plotModInstance_ = 0;

void
PlotMod::Instance ( PlotMod* pm )
{
	plotModInstance_ = pm;
}

PlotMod&
PlotMod::Instance()
{
	assert (plotModInstance_ != 0 );
	return *plotModInstance_;
}

PlotMod::PlotMod () : calledFromMacro_(false), exitOnErrorMessage_(true),
                      popupErrorMessage_(true)
{
	watch_ = 0;
}

bool
PlotMod::IsWindow( const char* driver )
{
	return !strcmp( MVSCREEN_DRIVER, driver );
}

bool
PlotMod::CalledFromMacro ( MvRequest& req )
{
	// Check if the request comes from a Macro
	int calledFromMacro = req("_CALLED_FROM_MACRO");

	// Only updates the plot environment if the request
	// comes from Macro. Otherwise, keeps the current status.
	if ( calledFromMacro )
		calledFromMacro_ = calledFromMacro;

	return calledFromMacro;
}

MvRequest
PlotMod::OutputFormat()
{
	if ( !outFormat_ ) 
		outFormat_ = MakeDefaultOutputFormat();

	return outFormat_;
}

void
PlotMod::OutputFormat( MvRequest& req)
{
	outFormat_ = req;
	if ( (const char*)outFormat_("DESTINATION") )
	{
		plotDestination_ = (const char*)outFormat_("DESTINATION");
		if ( plotDestination_ == MVPRINTER && (const char*)outFormat_("PRINTER_NAME") )
			printerName_ = (const char*)outFormat_("PRINTER_NAME");
	}
	else
		plotDestination_ = MVSCREEN;
}

MvRequest
PlotMod::MakeDefaultOutputFormat()
{
	MvRequest req( "PRINTER_MANAGER" );
	MvRequest gldriverReq( MVSCREEN_DRIVER );
	gldriverReq ( "DESTINATION" ) = MVSCREEN;
	req("OUTPUT_DEVICES") = gldriverReq;

	return req;
}

MvRequest
PlotMod::OutputFormatInfo()
{
	MvRequest info("OUTPUTINFO");
	info("DESTINATION")  = plotDestination_.c_str();
	info("PRINTER_NAME") = printerName_.c_str();
	info("NUMBER_COPIES") = (int)outFormat_("NUMBER_COPIES");
	MvRequest subReq = outFormat_.getSubrequest("OUTPUT_DEVICES");
	if ( subReq )
	{
		if ( (const char*)subReq("OUTPUT_NAME") )
			info("FILE_NAME") = subReq("OUTPUT_NAME");
		else if ( (const char*)subReq("OUTPUT_FULLNAME") )
			info("FILE_NAME") = subReq("OUTPUT_FULLNAME");
		else
			info("FILE_NAME") = "defaultFilename";  //default filename
	}

	return info;
}

#if 0
bool
PlotMod::CheckSetWindowOutputFormat( MvRequest& req )
{
	// Default value;
	isWindow_ = true;

	if ( IsParameterSet(req,"OUTPUT_DEVICES") )
	{
		// Output device definition was set by the user
		// Try to find the screen driver
		MvRequest outDev = req("OUTPUT_DEVICES");
		while ( outDev )
		{
			if ( strcmp(outDev.getVerb(),MVSCREEN_DRIVER) == 0 )
				return true;  //screen driver found

			outDev.advance();
		}

		// Screen driver not found
		isWindow_ = false;
		return false;
	}

	return true;
}
#endif


// ----------------------------------------------------------------------------
// PlotMod::infoMessage, warningMessage, errorMessage
// Receives message callbacks from Magics
// ----------------------------------------------------------------------------

void PlotMod::infoMessage(const string& msg)
{
    printMessage("Info: " + msg, false);
    //MetviewError (msg, "INFO");
    //messageToLogWindow (msg, LOG_INFO);
}

void PlotMod::warningMessage(const string& msg)
{
    printMessage("Warn: " + msg, true);
    //MetviewError (msg, "WARN");
    //messageToLogWindow (msg, LOG_WARN);
}

void PlotMod::errorMessage(const string& msg)
{
    string extra;

    // intercept the 'spherical harmonics' message and add our own information
    if (msg.find("Grib Decoder") != string::npos && 
        msg.find("Representation [sh]") != string::npos )
    {
        extra = "If you wish to plot this field, you should first convert it to a grid. "
                "If the data comes from a Mars Retrieval icon, you should set its GRID "
                "parameter; if it is from a GRIB file, you should use the GRIB Filter icon "
                "and set its GRID parameter.";
    }


    printMessage("Error: " + msg + extra, true);
    //MetviewError (msg, "ERROR");

    if(popupErrorMessage())
        UserMessage (msg + extra);
    //messageToLogWindow (msg, LOG_EROR);

    if(exitOnErrorMessage())
        exitWithError();
}



// --------------------------------------------------------------------------------------
// PlotModBatch::MetviewError
// Called by PlotMod::infoMessage, PlotMod::warningMessage and PlotMod::errorMessage, but
// the errorlevel is different for each.
// --------------------------------------------------------------------------------------

void PlotMod::MetviewError ( const string & message, const string & errorlevel )
{
    string fullMsg;
    bool priority = false;
    bool exit     = false;

    if ( errorlevel.length() )
    {
        fullMsg = errorlevel + ": ";

        if (errorlevel == "Warn" || errorlevel == "WARNING")
            priority = true;
        else if (errorlevel == "Error")
        {
            priority = true;
            exit     = true;
        }
    }

    fullMsg += message;
    printMessage(fullMsg, priority);

    if (priority)
        UserMessage(fullMsg);

    if (exit)
        exitWithError();
}


// the module will exit with an error code
void PlotMod::exitWithError()
{
    svc *service = MvApplication::instance().getService();
    if (service != NULL)
    {
        set_svc_err(service->id,1);
    }
}

// Timming functions
//Starts and names the session
void PlotMod::watchStart ( const char* txt )
{
	if( watch_ )
	{
		marslog(LOG_WARN,"stopwatch_start - watch already running, replace old watch!");
		delete watch_;
	}
	watch_ = new MvStopWatch( txt );
}

// Prints the laptime since the previous call to
// watchLaptime() or from watchStart()
void PlotMod::watchLaptime ( const char* txt )
{
	if( ! watch_ )
	{
		marslog(LOG_WARN,"stopwatch_laptime - watch not running, starting now!");
		watch_ = new MvStopWatch( "tictac" );
	}
	else
		watch_->lapTime( txt );
}

// Stops and prints a report
void PlotMod::watchStop()
{
	if( watch_ )
	{
		delete watch_;
		watch_ = 0;
	}
	else
		marslog(LOG_WARN,"stopwatch_stop - no watch running!");
}
