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

#pragma once

/********************************************************************************
  Application for Xsection.
  It takes a GRIB file as input (in addition to the values given by the user),
  and produces an NetCDF file as output. There is no metadata on output request,
  only the path to NetCDF file.

  First the GRIB while is read, and info about all parameters and level are stored.
  Then several flags is set, based on the data and the input request, to determine
  how the application should run.

  The file is rewound, and sorted by param, date, time, step and expver. All fields
  with the same values for the sorting parameters are one plot. If any of these
  values change, all data are written out as netcdf variables with names put
  together from the sorting values.
********************************************************************************/

#include "Xsect.h"

class CrossS : public Xsect
{
public:
    // Constructors
    CrossS();
    CrossS(const char* kw);

    // Get geographical coordinates and application parameters
    bool getCoordinates(MvRequest&, ApplicationInfo&);
    bool getAppParameters(MvRequest&, ApplicationInfo&) override;

    bool generateData(ApplicationInfo&, ParamMap&, MvNetCDF&, MvField&, const std::string&) override;

    // Create output request
    MvRequest createOutputRequest(ApplicationInfo&, ParamInfo*) override;

    // Check if parameters between two requests are consistent
    bool consistencyCheck(MvRequest&, MvRequest&) override;

    int computeGeographicalPoints(ApplicationInfo&, MvField*) override;

    bool fillValues(ApplicationInfo&, MvField&, double*) override;
    ParamInfo* plotVariable(ApplicationInfo& appInfo, ParamMap& params) override;

private:
    enum WindProjectionMode
    {
        ParallelWindProjection,
        NormalWindProjection,
        NoWindProjection
    };
    enum WindMode
    {
        Wind2DMode,
        Wind3DMode,
        Wind3DWithTMode,
        NoWindMode
    };
    enum OutputMode
    {
        ScalarOutput,
        VectorOutput
    };
    enum VerticalVelocityMode
    {
        Mv3VerticalVelocity,
        ScaledVerticalVelocity,
        ComputedVerticalVelocity
    };

    void init() override;
    bool generateXsectData(ApplicationInfo&, ParamMap&, MvNetCDF&, MvField&, const std::string&);
    bool generateLNSP(ApplicationInfo&, MvNetCDF&, ParamInfo*);
    bool wind2DValues(ApplicationInfo&, ParamMap&, MvNetCDF&, const std::string&, MvField&);
    bool wind3DValues(ApplicationInfo&, ParamMap&, MvNetCDF&, const std::string&, MvField&);
    void setHorCompFlags(bool, bool, bool, bool) override;
    OutputMode determineWindOutputMode() const;

#if 0
    void setHorComp(int, int, int, int);
#endif

    void computeWind2D(ApplicationInfo&, ParamInfo&, ParamInfo*, ParamInfo*);
    void computeWind3D(ApplicationInfo& appInfo, ParamInfo& par_uv, ParamInfo* par_u, ParamInfo* par_v,
                       ParamInfo* par_w);

    std::string titleVariable(ApplicationInfo&, ParamInfo*) override;

    // Get netCDF level variable name
    std::string getNetcdfLevelVarname(std::string&) override;

    // Get netCDF variable name
    std::string getNetcdfVarname(const std::string&) override;

    WindProjectionMode windProjection_{NoWindProjection};
    WindMode windMode_{NoWindMode};
    bool useWindIntensity_{false};
    bool needVectorOutput_{false};
    OutputMode outputMode_{ScalarOutput};
    std::string oroColour_{"CYAN"};
    double wScaling_{-100.};
    VerticalVelocityMode wMode_{Mv3VerticalVelocity};
    ParamInfo* plotVar_{nullptr};
};

//---------------------------------------------------------------------------------

// This class is defined for backwards compatibility with Metview 3.
// It should be removed in the future

class CrossSM3 : public CrossS
{
public:
    CrossSM3() :
        CrossS("PM_XSECT") {}

    void serve(MvRequest&, MvRequest&) override;
};
