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

#include <algorithm>

#include "Metview.h"
#include "MvObs.h"
#include "MvException.h"
#include "MvKeyProfile.h"
#include "MvMiscelaneous.h"

#include "BufrFilterDef.h"
#include "BufrFilterEngine.h"

class BufrFilter: public MvService
{
public:
   BufrFilter();
   ~BufrFilter() {}

   void serve( MvRequest&, MvRequest& );

private:
    BufrFilter(const BufrFilter&);
    void operator= (const BufrFilter&);

    void getParam(MvRequest& in,const std::string& param);
    void getParamVec(MvRequest& in,const std::string& param);

    BufrFilterDef def_;
};

BufrFilter::BufrFilter() : MvService("BUFRFILTER")
{

}

#if 0
void BufrFilter::getData(MvRequest &in)
{
   //-- D A T A --
   in.getValue( data_, "DATA" );


   //-- O U T P U T --
   const char* outStr = in_( "OUTPUT" );
   if ( !outStr )
      geoVectorType_ = 0;
   else if( std::string(outStr) == geoVectorName_[1] )
      geoVectorType_ = 1;
   else if( std::string(outStr) == geoVectorName_[2] )
      geoVectorType_ = 2;

  const char* fail = in_("FAIL_ON_ERROR");
  if( fail && strcmp( fail, "NO" ) == 0 )
     failOnError_ = false;
}
#endif




void BufrFilter::getParam(MvRequest& in,const std::string& param)
{
    if(const char* val=in(param.c_str()))
    {
        def_.add(param,std::string(val));
    }
}

void BufrFilter::getParamVec(MvRequest& in,const std::string& param)
{
    std::vector<string> vals;
    if(in.getValue(param,vals))
    {
       def_.add(param,metview::merge(vals,"/"));
    }
}

void BufrFilter::serve( MvRequest& in, MvRequest& out)
{
    in.print();

    std::string output;
    if(const char *outCh=in("OUTPUT"))
    {
        output=std::string(outCh);
    }

    if(output.empty())
        return;

    def_.add("EXTRACT","ON");

    std::string bufrFile;
    MvRequest dataReq=in("DATA");
    if(const char *fNameCh = dataReq("PATH"))
    {
        bufrFile=std::string(fNameCh);
    }

    if(bufrFile.empty())
    {
        return;
    }

    //if(O)

    getParam(in,"CUSTOM_COUNT");

    getParam(in,"PARAMETER_COUNT");
    std::string cntVal=def_.value("PARAMETER_COUNT");
    if(!cntVal.empty())
    {
        int cnt=metview::fromString<int>(cntVal);
        for(int i=0; i < cnt; i++)
        {
            std::string numStr=metview::toString(i+1);
            getParam(in,"PARAMETER_" + numStr);
            getParam(in,"PARAMETER_RANK_" + numStr);
            getParam(in,"PARAMETER_OPERATOR_" + numStr);
            getParamVec(in,"PARAMETER_VALUE_" + numStr);
        }
    }

    getParam(in,"COORDINATE_COUNT");
    cntVal=def_.value("COORDINATE_COUNT");
    if(!cntVal.empty())
    {
        int cnt=metview::fromString<int>(cntVal);
        for(int i=0; i < cnt; i++)
        {
            std::string numStr=metview::toString(i+1);
            getParam(in,"COORDINATE_" + numStr);
            getParamVec(in,"COORDINATE_RANK_" + numStr);
            getParam(in,"COORDINATE_OPERATOR_" + numStr);
            getParamVec(in,"COORDINATE_VALUE_" + numStr);
        }
    }

    getParam(in,"EXTRACT_MODE");
    getParam(in,"EXTRACT_COORDINATE");
    getParam(in,"EXTRACT_DATE");
    getParam(in,"MISSING_DATA");

    getParamVec(in,"MESSAGE_INDEX");
    getParamVec(in,"EDITION");
    getParamVec(in,"CENTRE");
    getParamVec(in,"SUBCENTRE");
    getParamVec(in,"DATA_TYPE");
    getParamVec(in,"DATA_SUBTYPE");

    getParam(in,"DATEMODE");
    getParam(in,"DATE");
    getParam(in,"TIME");
    getParam(in,"WINDOW_IN_MINUTES");
    getParam(in,"DATE_1");
    getParam(in,"TIME_1");
    getParam(in,"DATE_2");
    getParam(in,"TIME_2");

    getParamVec(in,"AREA");

    getParam(in,"IDENT_KEY");
    getParamVec(in,"IDENT_VALUE");

    getParam(in,"CUSTOM_COUNT");
    cntVal=def_.value("CUSTOM_COUNT");
    if(!cntVal.empty())
    {
        int cnt=metview::fromString<int>(cntVal);
        for(int i=0; i < cnt; i++)
        {
            std::string numStr=metview::toString(i+1);
            getParam(in,"CUSTOM_KEY_" + numStr);
            getParam(in,"CUSTOM_RANK_" + numStr);
            getParam(in,"CUSTOM_OPERATOR_" + numStr);
            getParamVec(in,"CUSTOM_VALUE_" + numStr);
        }
    }

    BufrFilterEngine filter(bufrFile,BufrFilterEngine::MetviewMode,0);

    //The object to store the extracted values
    MvKeyProfile* extractedProf=new MvKeyProfile("result");

    std::string resFile(marstmp());
    MvRequest x("GEOPOINTS");
    x("TEMPORARY") = 1;
    x("PATH") = resFile.c_str();

#if 0
    outfile_.open( fileName, ios::out );

    outfile_ << "#GEO" << endl;

    if( geoVectorType_ > 0 )
       outfile_ << "#FORMAT " << geoVectorName_[geoVectorType_] << endl;

    if ( geoVectorType_ > 0 )
       outfile_ << "PARAMETER = " << param_ << mySeparator << param2_ << endl;
    else
       outfile_ << "PARAMETER = " << param_ << endl;

    outfile_ << "#lat" << mySeparator << "long" << mySeparator
             << "level" << mySeparator << "date" << mySeparator
             << "time" << mySeparator;
#endif

    try
    {
        filter.run(def_,resFile,extractedProf);
        filter.toGeopoints(resFile);
    }
    catch(MvException& e)
    {
        marslog(LOG_EROR,e.what());
    }

    out = x;
}

int main(int argc,char **argv )
{
   MvApplication theApp( argc, argv );
   BufrFilter bf;

   theApp.run();
}
