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

//
// .NAME:
//  MagicsTranslator
//
// .AUTHOR:
//  Gilberto Camara, Baudouin Raoult and Fernando Ii
//
// .SUMMARY:
//  A general class for translatiopn of METVIEW requests
//  into MAGICS requests
//
// .CLIENTS:
//  MagicsAction, MapView
//
// .RESPONSABILITIES:
//  - Read the incoming METVIEW requests
//  - Find the appropriate MAGIS equivalents
//  - Provide new magics request
//
// .COLLABORATORS:
//
// .BASE CLASS:
//  Prototype
//
// .DERIVED CLASSES:
//  GribTranslator, ImageTranslator, BufrTranslator
//
// .REFERENCES:
//
//
#pragma once

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

class MagicsTranslator;

struct MagicsTranslatorTraits
{
    using Type = MagicsTranslator;
    static Type& DefaultObject();
};

class MagicsTranslator : public Prototype<MagicsTranslatorTraits>
{
public:
    // Contructors
    MagicsTranslator(const Cached& actionName) :
        Prototype<MagicsTranslatorTraits>(actionName, this) {}

    // Destructor
    ~MagicsTranslator() override;

    // Translator functions
    virtual MvRequest Execute(const MvRequest&) = 0;
    virtual MvRequest Execute(const MvRequest&, const MvRequest&) = 0;
    virtual MvRequest Execute(const MvRequest&, const MvRequest&, const MvRequest&) = 0;
};

class GribTranslator : public MagicsTranslator
{
public:
    // Contructors
    GribTranslator(const Cached& actionName) :
        MagicsTranslator(actionName) {}

    // Destructor
    ~GribTranslator() override = default;

    MvRequest Execute(const MvRequest&) override
    {
        return {"EMPTY"};
    }
    MvRequest Execute(const MvRequest&, const MvRequest&) override
    {
        return {"EMPTY"};
    }
    MvRequest Execute(const MvRequest&, const MvRequest&, const MvRequest&) override;

    static MagicsTranslator& Instance();  // for the default object
};

class BufrTranslator : public MagicsTranslator
{
public:
    // Contructors
    BufrTranslator(const Cached& actionName) :
        MagicsTranslator(actionName) {}

    // Destructor
    ~BufrTranslator() override = default;

    MvRequest Execute(const MvRequest&) override
    {
        return {"EMPTY"};
    }
    MvRequest Execute(const MvRequest&, const MvRequest&) override
    {
        return {"EMPTY"};
    }
    MvRequest Execute(const MvRequest&, const MvRequest&, const MvRequest&) override;
};

class ObsTranslator : public MagicsTranslator
{
public:
    // Contructors
    ObsTranslator(const Cached& actionName) :
        MagicsTranslator(actionName) {}

    // Destructor
    ~ObsTranslator() override = default;

    MvRequest Execute(const MvRequest&) override;
    MvRequest Execute(const MvRequest& req, const MvRequest&) override
    {
        return this->Execute(req);
    }
    MvRequest Execute(const MvRequest& req, const MvRequest&, const MvRequest&) override
    {
        return this->Execute(req);
    }
};

class CoastTranslator : public MagicsTranslator
{
public:
    // Contructors
    CoastTranslator(const Cached& actionName) :
        MagicsTranslator(actionName) {}

    // Destructor
    ~CoastTranslator() override = default;

    MvRequest Execute(const MvRequest&) override;
    MvRequest Execute(const MvRequest& req, const MvRequest&) override
    {
        return this->Execute(req);
    }
    MvRequest Execute(const MvRequest& req, const MvRequest&, const MvRequest&) override
    {
        return this->Execute(req);
    }
};

class ContTranslator : public MagicsTranslator
{
public:
    // Contructors
    ContTranslator(const Cached& actionName) :
        MagicsTranslator(actionName) {}

    // Destructor
    ~ContTranslator() override = default;

    MvRequest Execute(const MvRequest&) override;
    MvRequest Execute(const MvRequest& req, const MvRequest&) override
    {
        return this->Execute(req);
    }
    MvRequest Execute(const MvRequest& req, const MvRequest&, const MvRequest&) override
    {
        return this->Execute(req);
    }
};

class MContTranslator : public MagicsTranslator
{
public:
    // Contructors
    MContTranslator(const Cached& actionName) :
        MagicsTranslator(actionName) {}

    // Destructor
    ~MContTranslator() override = default;

    MvRequest Execute(const MvRequest&) override;
    MvRequest Execute(const MvRequest& req, const MvRequest&) override
    {
        return this->Execute(req);
    }
    MvRequest Execute(const MvRequest& req, const MvRequest&, const MvRequest&) override
    {
        return this->Execute(req);
    }
};

class TextTranslator : public MagicsTranslator
{
public:
    // Contructors
    TextTranslator(const Cached& actionName) :
        MagicsTranslator(actionName) {}

    // Destructor
    ~TextTranslator() override = default;

    MvRequest Execute(const MvRequest&) override;
    MvRequest Execute(const MvRequest& req, const MvRequest&) override
    {
        return this->Execute(req);
    }
    MvRequest Execute(const MvRequest& req, const MvRequest&, const MvRequest&) override
    {
        return this->Execute(req);
    }
};

class AxisTranslator : public MagicsTranslator
{
public:
    // Contructors
    AxisTranslator(const Cached& actionName) :
        MagicsTranslator(actionName) {}

    // Destructor
    ~AxisTranslator() override = default;

    MvRequest Execute(const MvRequest&) override;
    MvRequest Execute(const MvRequest& req, const MvRequest&) override
    {
        return this->Execute(req);
    }
    virtual MvRequest Execute(const MvRequest& req, const MvRequest&, const MvRequest&)
    {
        return this->Execute(req);
    }
};

class GraphTranslator : public MagicsTranslator
{
public:
    // -- Contructors
    GraphTranslator(const Cached& actionName) :
        MagicsTranslator(actionName) {}

    // -- Destructor
    ~GraphTranslator() override = default;

    MvRequest Execute(const MvRequest&) override;
    MvRequest Execute(const MvRequest& req, const MvRequest&) override
    {
        return this->Execute(req);
    }
    MvRequest Execute(const MvRequest& req, const MvRequest&, const MvRequest&) override
    {
        return this->Execute(req);
    }
};

class PageTranslator : public MagicsTranslator
{
public:
    // Contructors
    PageTranslator(const Cached& actionName) :
        MagicsTranslator(actionName) {}

    // Destructor
    ~PageTranslator() override = default;

    MvRequest Execute(const MvRequest&) override;
    MvRequest Execute(const MvRequest& req, const MvRequest&) override
    {
        return this->Execute(req);
    }
    MvRequest Execute(const MvRequest& req, const MvRequest&, const MvRequest&) override
    {
        return this->Execute(req);
    }

protected:
    void loadPredefAreas();
    MvRequest findPredefArea(const std::string& name);

    MvRequest predefAreas_;
};

class GribVectorsTranslator : public MagicsTranslator
{
public:
    // -- Contructors
    GribVectorsTranslator(const Cached& actionName) :
        MagicsTranslator(actionName) {}

    // -- Destructor
    ~GribVectorsTranslator() override = default;

    MvRequest Execute(const MvRequest&) override
    {
        return {"EMPTY"};
    }
    MvRequest Execute(const MvRequest&, const MvRequest&) override
    {
        return {"EMPTY"};
    }
    MvRequest Execute(const MvRequest&, const MvRequest&, const MvRequest&) override;
};

class WindTranslator : public MagicsTranslator
{
public:
    // Contructors
    WindTranslator(const Cached& actionName) :
        MagicsTranslator(actionName) {}

    // Destructor
    ~WindTranslator() override = default;

    MvRequest Execute(const MvRequest&) override;
    MvRequest Execute(const MvRequest& req, const MvRequest&) override
    {
        return this->Execute(req);
    }
    MvRequest Execute(const MvRequest& req, const MvRequest&, const MvRequest&) override
    {
        return this->Execute(req);
    }
};

class MWindTranslator : public MagicsTranslator
{
public:
    // Contructors
    MWindTranslator(const Cached& actionName) :
        MagicsTranslator(actionName) {}

    // Destructor
    ~MWindTranslator() override = default;

    MvRequest Execute(const MvRequest&) override;
    MvRequest Execute(const MvRequest& req, const MvRequest&) override
    {
        return this->Execute(req);
    }
    MvRequest Execute(const MvRequest& req, const MvRequest&, const MvRequest&) override
    {
        return this->Execute(req);
    }
};

class NetCDFTranslator : public MagicsTranslator
{
public:
    // Contructors
    NetCDFTranslator(const Cached& actionName) :
        MagicsTranslator(actionName) {}

    // Destructor
    ~NetCDFTranslator() override = default;

    MvRequest Execute(const MvRequest&) override
    {
        return MvRequest("EMPTY");
    }
    MvRequest Execute(const MvRequest&, const MvRequest&) override
    {
        return {"EMPTY"};
    }
    MvRequest Execute(const MvRequest&, const MvRequest&, const MvRequest&) override;
};

class VoidTranslator : public MagicsTranslator
{
public:
    // Contructors
    VoidTranslator(const Cached& actionName) :
        MagicsTranslator(actionName) {}

    // Destructor
    ~VoidTranslator() override = default;

    MvRequest Execute(const MvRequest&) override;
    MvRequest Execute(const MvRequest&, const MvRequest&) override;
    MvRequest Execute(const MvRequest&, const MvRequest&, const MvRequest&) override;
};

class VisDefTranslator : public MagicsTranslator
{
public:
    // Contructors
    VisDefTranslator(const Cached& actionName) :
        MagicsTranslator(actionName) {}

    // Destructor
    ~VisDefTranslator() override = default;

    MvRequest Execute(const MvRequest&) override;
    MvRequest Execute(const MvRequest& req, const MvRequest&) override
    {
        return this->Execute(req);
    }
    MvRequest Execute(const MvRequest& req, const MvRequest&, const MvRequest&) override
    {
        return this->Execute(req);
    }
};

class GeopointsTranslator : public MagicsTranslator
{
public:
    // Contructors
    GeopointsTranslator(const Cached& actionName) :
        MagicsTranslator(actionName) {}

    // Destructor
    ~GeopointsTranslator() override = default;

    MvRequest Execute(const MvRequest&) override
    {
        return {"EMPTY"};
    }
    MvRequest Execute(const MvRequest&, const MvRequest&) override
    {
        return {"EMPTY"};
    }
    MvRequest Execute(const MvRequest&, const MvRequest&, const MvRequest&) override;
};

class SymbolTranslator : public MagicsTranslator
{
public:
    // Contructors
    SymbolTranslator(const Cached& actionName) :
        MagicsTranslator(actionName) {}

    // Destructor
    ~SymbolTranslator() override = default;

    MvRequest Execute(const MvRequest&) override;
    MvRequest Execute(const MvRequest& req, const MvRequest&) override
    {
        return this->Execute(req);
    }
    MvRequest Execute(const MvRequest& req, const MvRequest&, const MvRequest&) override
    {
        return this->Execute(req);
    }
};

class ImportTranslator : public MagicsTranslator
{
public:
    // Contructors
    ImportTranslator(const char* actionName) :
        MagicsTranslator(actionName) {}

    // Destructor
    ~ImportTranslator() override = default;

    MvRequest Execute(const MvRequest&) override;
    MvRequest Execute(const MvRequest& req, const MvRequest&) override
    {
        return this->Execute(req);
    }
    MvRequest Execute(const MvRequest& req, const MvRequest&, const MvRequest&) override
    {
        return this->Execute(req);
    }
};

class ThermoTranslator : public MagicsTranslator
{
public:
    // Contructors
    ThermoTranslator(const char* actionName) :
        MagicsTranslator(actionName) {}

    // Destructor
    ~ThermoTranslator() override = default;

    MvRequest Execute(const MvRequest&, const MvRequest&) override;
    MvRequest Execute(const MvRequest&) override
    {
        return {"EMPTY"};
    }
    MvRequest Execute(const MvRequest&, const MvRequest&, const MvRequest&) override
    {
        return {"EMPTY"};
    }
};

class ThermoGridTranslator : public MagicsTranslator
{
public:
    ThermoGridTranslator(const char* actionName) :
        MagicsTranslator(actionName) {}

    ~ThermoGridTranslator() override = default;

    MvRequest Execute(const MvRequest&, const MvRequest&) override { return {"EMPTY"}; }
    MvRequest Execute(const MvRequest&) override;
    MvRequest Execute(const MvRequest&, const MvRequest&, const MvRequest&) override { return {"EMPTY"}; }
};

class InputBoxplotTranslator : public MagicsTranslator
{
public:
    using MagicsTranslator::MagicsTranslator;
    ~InputBoxplotTranslator() override = default;

    MvRequest Execute(const MvRequest&) override;
    MvRequest Execute(const MvRequest& req, const MvRequest&) override { return Execute(req); }
    MvRequest Execute(const MvRequest& req, const MvRequest&, const MvRequest&) override
    {
        return Execute(req);
    }
};


class TableTranslator : public MagicsTranslator
{
public:
    // Contructors
    TableTranslator(const char* actionName) :
        MagicsTranslator(actionName) {}

    // Destructor
    ~TableTranslator() override = default;

    MvRequest Execute(const MvRequest&) override;
    MvRequest Execute(const MvRequest& req, const MvRequest&) override
    {
        return this->Execute(req);
    }
    MvRequest Execute(const MvRequest& req, const MvRequest&, const MvRequest&) override
    {
        return this->Execute(req);
    }
};
