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

//--

#ifndef DIVROT_H
#define DIVROT_H

#include "Metview.h"

#define VORTICITY    138
#define DIVERGENCE   155


extern "C"
void vod2uv_( fortfloat* VOR
            , fortfloat* DIV
            , fortint*   KTIN
            , fortfloat* U
            , fortfloat* V
            , fortint*   KTOUT
            );

const string cVORTICITY ( "138.128" );
const string cDIVERGENCE( "155.128" );
const string cSPECTRAL( "sh" );

enum eParam
{
   eVorticity,
   eDivergence,
   eVorticityAndDivergence,
   eUnknown
};

enum eResultParam  // what we would like to compute
{
    eRotational,
    eDivergent,
    eUV,
    eResultUnknown
};


class Divrot : public MvService {
protected :
    char         Dsmoothing[4];   // smoothing (1 Yes/0 No)
    eParam       Dparam;          // eVorticity or eDivergence
    eResultParam DresultParam;    // eRotational, eDivergent or eUV
    int          DtruncIn;        // truncation of input field
    int          DtruncOut;       // output truncation
    double       Dfltc;           // constant
    double       Dmfltexp;        // exponent
    int          Dnfield;         // number of fields
    int          Dnfield2;        // number of fields (used if deriving U/V)
    MvFieldSet   Dfieldset;       // Vorticity or divergence field set
    MvFieldSet   Dfieldset2;      // Vorticity or divergence field set (used if deriving U/V)
    string       DfileOut;        // tmp output file name
    long         DoutputValsLen;  // nr of (truncated) U/V values

public:
    Divrot(char* a) : MvService(a) {}
    ~Divrot() {}
    void serve(MvRequest&,MvRequest&);

    virtual bool GetData(MvRequest&) = 0;
    bool GetDataGen(MvRequest&);
    bool Apply(MvRequest&);
    int  GetField (MvRequest&, int, MvFieldSet&);

    bool isValidData_DVVALID( grib_handle* gh );
    bool checkOutputTruncation( grib_handle* gh );
    bool convert_DIVROT( MvRequest& out );
    bool smooth_BPPSMTH( grib_handle* gh );
    bool appendWindComponent( grib_handle* gh );
    bool badRetVal( int ret, const char* gribApiFunc, const char* MvFunc );
};

class Rotwind : public Divrot
{
public :
    Rotwind(char* a) : Divrot(a) {}
    virtual bool GetData(MvRequest&);
};

class Divwind : public Divrot
{
public :
    Divwind(char* a) : Divrot(a) {}
    virtual bool GetData(MvRequest&);
};

class UVwind : public Divrot
{
public :
    UVwind(char* a) : Divrot(a) {}
    virtual bool GetData(MvRequest&);
};

#endif
//-- DIVROT_H
