/***************************** 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 "inc_iostream.h"

#include <MvRequest.h>
#include <MvRequestUtil.hpp>

//
// FUNCTION: CopyAndRemoveParameters
//
// PURPOSE : To copy a request into another removing all
//           parameters that start with a certain "prefix"
//
// INPUT   : - A request
//           - Prefix to be used for removing parameters
//
// OUTPUT  : - A request which does not contain the desired params
//


void
CopyAndRemoveParameters ( const MvRequest& inRequest,
			  MvRequest& outRequest,
			  const char* prefix )
{
	int length = strlen ( prefix );

	int count = inRequest.countParameters();

	for(int i = 0; i < count ; i++)
	{
		const char* param = inRequest.getParameter(i);
		if(strncmp(param, prefix, length ) != 0)
		{
			int n = inRequest.countValues(param);
			outRequest.unsetParam(param);
			for(int j = 0; j < n ; j++)
			{
				const char *value= 0;
				inRequest.getValue(value,param,j);
				outRequest.addValue(param,value);
			}
		}
	}

}

//
// FUNCTION: CopySomeParameters
//
// PURPOSE : To copy the Parameters which start with a certain prefix
//           from one request to another
//
// INPUT   : - A request
//           - Prefix to be used for copy parameters
//           - Option to overwrite existing output parameters
//
// OUTPUT  : - A request which contain the desired params
//
void
CopySomeParameters ( const MvRequest&  inRequest,
		     MvRequest&  outRequest,
		     const char* prefix,
		     bool        overwrite )
{
	int length = strlen ( prefix );

	int count = inRequest.countParameters();

	for(int i = 0; i < count ; i++)
	{
		const char* param = inRequest.getParameter(i);
		if(strncmp(param, prefix, length ) == 0)
		{
			if ( !overwrite && IsParameterSet ( outRequest, param ) ) continue;
			int n = inRequest.countValues(param);
			for(int j = 0; j < n ; j++)
			{
				const char *value= 0;
				inRequest.getValue(value,param,j);
				if ( j == 0 ) outRequest.setValue(param,value);
				else          outRequest.addValue(param,value);
			}
		}
	}

}

//
// FUNCTION: CopySomeParameters
//
// PURPOSE : To copy the Parameters which start with a certain prefix
//           from one request to another changing prefix by a new prefix
//
// INPUT   : - A request
//           - Prefix to be used for copy parameters
//           - New prefix to be used instead of prefix
//
// OUTPUT  : - A request which contain the desired params
//
void
CopySomeParameters ( const MvRequest& inRequest,
		     MvRequest& outRequest,
		     const char* prefix,
		     const char* newPrefix )
{
	int length = strlen ( prefix );

	int count = inRequest.countParameters();
	for ( int i = 0; i < count ; i++ )
	{
		const char* param = inRequest.getParameter(i);
		if(strncmp(param, prefix, length ) == 0)
		{
			int n = inRequest.countValues(param);
			Cached auxPar ( (const char *)(param + length) );
			Cached newparam = Cached (newPrefix) + auxPar;
			for ( int j = 0; j < n ; j++ )
			{
				const char *value= 0;
				inRequest.getValue(value,param,j);
				outRequest.addValue(newparam,value);
			}
		}
	}

}

//
// FUNCTION: CopySomeParameters
//
// PURPOSE : To copy the Parameters which finish with a certain suffix
//           from one request to another
//
// INPUT   : - A request
//           - Sufix to be used for copy parameters
//
// OUTPUT  : - A request which contain the desired params
//
void
CopySomeParameters ( const MvRequest&  inRequest,
               MvRequest&  outRequest,
               const string& sufix )
{
     unsigned int length = sufix.size();
     int count  = inRequest.countParameters();
     for(int i = 0; i < count ; i++)
     {
          string param = (const char*)inRequest.getParameter(i);
          if ( param.size() < length ) // no need to compare
               continue;

          if( param.compare(param.size()-length,length,sufix ) == 0)
          {
               const char* cparam = param.c_str();
               int n = inRequest.countValues(cparam);
               for(int j = 0; j < n ; j++)
               {
                    const char *value= 0;
                    inRequest.getValue(value,cparam,j);
                    if ( j == 0 ) outRequest.setValue(cparam,value);
                    else          outRequest.addValue(cparam,value);
               }
          }
     }

}

//
// FUNCTION: RemoveParameters
//
// PURPOSE : Remove all parameters that start with a certain "prefix"
//
// INPUT   : - A request
//           - Prefix to be used for removing parameters
//
// OUTPUT  : - A request which does not contain the desired params
//
void
RemoveParameters ( MvRequest& req, const char* prefix )
{
	MvRequest aux = req;
	int length = strlen ( prefix );
	int count = req.countParameters();
	for(int i = 0; i < count ; i++)
	{
		const char* param = aux.getParameter(i);
		if(strncmp(param, prefix, length ) == 0)
			req.unsetParam(param);
	}
}

//
// FUNCTION: AreEqualRequests
//
// PURPOSE : Compare two requests.
//
// INPUT   : - Two requests
//
// OUTPUT  : - true: If the input requests have the same number of parameters and
//                   the parameters names and values are equal.
//           - false: otherwise
//
// OBS     : Comparison only between parameter values, if there are subrequests
//           the result is unpredictable
bool
AreEqualRequests ( MvRequest& req1, MvRequest& req2 )
{
	int count = req1.countParameters();
	int i     = -1;
	if ( count == req2.countParameters() )
	{
		for ( i = 0; i < count ; i++)
		{
			const char* param = req1.getParameter(i);
			int n = req1.countValues(param);
			int j;
			for ( j = 0; j < n ; j++)
			{
				const char *value2 = 0;
				req2.getValue(value2,param,j);
				if( ! value2 )
					return false;  //-- 'param' missing from req2!

				const char *value1 = 0;
				req1.getValue(value1,param,j);
				if ( strcmp ( value1, value2 ) )
					break;
			}
			if ( j != n )
				break;
		}
	}
	if ( i != count )
		return false;
	else
		return true;
}

bool
IsParameterSet ( MvRequest& request, const char* paramSought )
{
   int count = request.countParameters();

   for( int i = 0; i < count ; i++ )
   {
      const char* paramFound = (const char*)request.getParameter(i);

      if ( strcmp(paramFound,paramSought) == 0 )
         return true;
   }

   return false;
}

bool
SetIfValue( MvRequest& targetReq, const char* targetParam, const char*  val )
{
	if( val )
	{
		targetReq( targetParam ) = val;
		return true;
	}

	return false;
}

void
MergeTextParameters ( MvRequest&  inRequest,
		      MvRequest&  outRequest,
		      bool        overwrite )
{
	int i;

	// Move output TEXT_LINE_* forward according to
	// input TEXT_LINE_COUNT
	int inCount  = inRequest ("TEXT_LINE_COUNT");
	int outCount = outRequest("TEXT_LINE_COUNT");
	if ( inCount )
	{
		// Define constants
		char   saux[13];       //TEXT_LINE_*
		int    MAXCOUNT = 10;
		int    size;

		strcpy (saux ,"TEXT_LINE_");
		size = strlen(saux);

		// Check maximum number of merged lines
		int maxline = ((inCount + outCount) > MAXCOUNT) ? MAXCOUNT : (inCount + outCount);

		// Move texts
		for(i = maxline; i > inCount ; i--)
		{
			sprintf(saux+size, "%d", i-inCount);
			const char* text = outRequest(saux);
			sprintf(saux+size, "%d", i);
			if ( text )
				outRequest(saux) = text;
			else
				outRequest.unsetParam ( saux );
		}

		// Clear initial TEXT_LINE_* from the output request
		for(i = 1; i <= inCount ; i++)
		{
			sprintf(saux+size, "%d", i);
			outRequest.unsetParam ( saux );
		}

		// Update output TEXT_LINE_COUNT
		outRequest("TEXT_LINE_COUNT") = maxline;
	}

	// Copy remaining parameters
	CopySomeParameters (inRequest, outRequest, "TEXT_", overwrite);
}

void
CopyParametersAndStackingOrder ( const MvRequest& inRequestOld, const MvRequest& inRequestNew, int index, MvRequest& outRequest )
{
   // Create a new request based on inRequestNew and taking into consideration the
   // drawing order info. If there is a new drawing order info then update it too;
   // otherwise, keep the previous one (if it exists).
   outRequest = inRequestNew;
   if ( index != -1 || !inRequestOld )
      outRequest("_STACKING_ORDER") = index;
   else
   {
      const char* corder = (const char*)inRequestOld("_STACKING_ORDER");
      outRequest("_STACKING_ORDER") = (int)(corder ? atoi(corder) : -1);
   }

   return;
}
