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

// ------------------------------------------------------------------
// CONTOUR - PCONT
// CONTOUR_SHADE ON/OFF
// OFF

// CONTOUR_SHADE_TECHNIQUE POLYGON_SHADING/CELL_SHADING/MARKER
// POLYGON_SHADING

// CONTOUR_SHADE_METHOD DOT/HATCH/AREA_FILL
// DOT
// ------------------------------------------------------------------


// ------------------------------------------------------------------
// WIND - PWIND

// WIND_FIELD_TYPE ARROWS/FLAGS/STREAMLINES
// ARROWS
// ------------------------------------------------------------------


// ------------------------------------------------------------------
// OBS - POBS
// ------------------------------------------------------------------


// ------------------------------------------------------------------
// Coastlines - PCOAST

// MAP_COASTLINE ON/OFF
// ON

// MAP_COASTLINE_LAND_SHADE ON/OFF
// OFF

// MAP_COASTLINE_SEA_SHADE ON/OFF
// OFF
// ------------------------------------------------------------------


// ------------------------------------------------------------------
// TEXT - PTEXT

// TEXT_MODE TITLE/POSITIONAL
// TITLE
// ------------------------------------------------------------------


// ------------------------------------------------------------------
// GRAPH - PGRAPH

// GRAPH_TYPE CURVE/BAR/AREA
// CURVE

// GRAPH_SHADE ON/OFF
// ON

// GRAPH_SHADE_STYLE  DOT/HATCH/AREA_FILL
// DOT
// ------------------------------------------------------------------


// ------------------------------------------------------------------
// SYMBOL - PSYMB
// ------------------------------------------------------------------


// ------------------------------------------------------------------
// AXIS - PAXIS
// ------------------------------------------------------------------

// ------------------------------------------------------------------
// PCONT
// - 700 CONTOUR_SHADE OFF
//    CONTOUR_SHADE ON
// - 200 CONTOUR_SHADE_TECHNIQUE CELL_SHADING
// - 700 CONTOUR_SHADE_TECHNIQUE MARKER
//    CONTOUR_SHADE_TECHNIQUE POLYGON_SHADING
// - 700 CONTOUR_SHADE_METHOD DOT
// - 700 CONTOUR_SHADE_METHOD HATCH
// - 300 CONTOUR_SHADE_METHOD AREA_FILL
// ------------------------------------------------------------------

// ------------------------------------------------------------------
// PWIND
// - 800 WIND_FIELD_TYPE ARROWS
// - 800 WIND_FIELD_TYPE FLAGS
// - 800 WIND_FIELD_TYPE STREAMLINES
// ------------------------------------------------------------------


// ------------------------------------------------------------------
// POBS
// - 900
// ------------------------------------------------------------------

// ------------------------------------------------------------------
// PCOAST
// - FIRST/LAST
// - 000 FIRST
// - 999 LAST
// - 999 MAP_COASTLINE OFF
//    MAP_COASTLINE ON
// - 000 MAP_COASTLINE_LAND_SHADE / MAP_COASTLINE_SEA_SHADE ON
// - 999 MAP_COASTLINE_LAND_SHADE / MAP_COASTLINE_SEA_SHADE OFF
// ------------------------------------------------------------------

// ------------------------------------------------------------------
// PTEXT
// - 900 TEXT_MODE TITLE
// - 900 TEXT_MODE POSITIONAL
// ------------------------------------------------------------------

// ------------------------------------------------------------------
// PGRAPH
// - 800 GRAPH_TYPE CURVE
// - 700 GRAPH_TYPE BAR
// - 700 GRAPH_TYPE AREA
// - 700 GRAPH_SHADE OFF
//    GRAPH_SHADE ON
// - 700 GRAPH_SHADE_STYLE DOT
// - 700 GRAPH_SHADE_STYLE HATCH
// - 300 GRAPH_SHADE_STYLE AREA_FILL
// ------------------------------------------------------------------

// ------------------------------------------------------------------
// PSYMB
// - 900
// ------------------------------------------------------------------

// ------------------------------------------------------------------
// PAXIS
// - 100
// ------------------------------------------------------------------

#include "DrawingPriority.h"

#include <iomanip>

#include "MvRequest.h"
#include "ObjectList.h"
#include "ObjectInfo.h"
#include "PlotMod.h"
#include "MvLog.h"

DrawingPriority::DrawingPriority()
{
    MvRequest drawPriorRequest;

    drawPriorRequest = ObjectList::UserDefaultRequest("DRAWING_PRIORITY");

    MvRequest expRequest = ObjectList::ExpandRequest(drawPriorRequest, EXPAND_DEFAULTS);

    int count = expRequest.countParameters();
    int i = 0;
    int priorValue = 0;
    std::string keyString;
    for (i = 0; i < count; i++) {
        keyString = expRequest.getParameter(i);
        Cached tmpcached = expRequest(keyString.c_str());
        if (isalpha(tmpcached[0])) {
            if (tmpcached == Cached("FIRST"))
                priorValue = 0;
            else
                priorValue = 999;
        }
        else
            priorValue = atoi(tmpcached);

        mySet_.insert(keyString);
        myMap_[keyString] = priorValue;
    }
}

DrawingPriority::~DrawingPriority() = default;

void DrawingPriority::SetPriority(MvRequest& request)
{
    MvRequest expRequest = ObjectList::ExpandRequest(request, EXPAND_DEFAULTS);

    int count = expRequest.countParameters();
    int i = 0, priorValue = 0;
    std::string keyString;
    for (i = 0; i < count; i++) {
        keyString = expRequest.getParameter(i);
        Cached tmpcached = expRequest(keyString.c_str());
        if (isalpha(tmpcached[0])) {
            if (tmpcached == Cached("FIRST"))
                priorValue = 0;
            else
                priorValue = 999;
        }
        else
            priorValue = atoi(tmpcached);

        if (IsValidKey(keyString))
            myMap_[keyString] = priorValue;
        else {
            MvLog().popup().err() << "uPlot DrawingPriority::SetPriority-> Invalid key: " << keyString;
        }
    }
}

int DrawingPriority::Priority(MvRequest& request)
{
    MvRequest expRequest = ObjectList::ExpandRequest(request, EXPAND_DEFAULTS);

    std::string keyString(expRequest.getVerb() ? expRequest.getVerb() : "");
    if (!IsValidKey(keyString)) {
        int count = expRequest.countParameters();
        int i = 0;
        for (i = 0; i < count; i++) {
            std::string param = expRequest.getParameter(i);
            if (param.size() != 0) {
                if (param.find("_") == 0)
                    continue;
            }
            std::string pairString(keyString + std::string("_") + param);

            if (expRequest.countValues(param.c_str())) {
                // Use only the first value
                const char* value = nullptr;
                expRequest.getValue(value, param.c_str(), 0);
                pairString += std::string("_") + std::string(value);
            }

            if (IsValidKey(pairString)) {
                keyString = pairString;
                break;
            }
        }
    }
    return GetPriority(keyString);
}

int DrawingPriority::IsValidKey(std::string keyString)
{
    auto setIter = mySet_.find(keyString);
    if (setIter == mySet_.end())
        return false;

    return true;
}

int DrawingPriority::GetPriority(std::string keyString)
{
    auto mapIter = myMap_.find(keyString);
    if (mapIter == myMap_.end())  // arbitrary value
    {
        //		COUT << keyString << " keyString NOT found on MAP!!!" << std::endl;
        return 100;
    }

    return (*mapIter).second;
}

// Describe for saving into a macro
std::string
DrawingPriority::DescribeYourself(ObjectInfo& description, std::string pageName)
{
    MvRequest drawPriorRequest("DRAWING_PRIORITY");

    // Using system defaults instead of user defaults
    MvRequest defDrawPriorRequest;
    defDrawPriorRequest = ObjectList::CreateDefaultRequest("DRAWING_PRIORITY");

    MvRequest defRequest = ObjectList::ExpandRequest(defDrawPriorRequest,
                                                     EXPAND_DEFAULTS);

    int count = defRequest.countParameters();

    int i = 0;
    int defPriorValue = 0;
    std::string keyString;
    for (i = 0; i < count; i++) {
        keyString = defRequest.getParameter(i);
        Cached tmpcached = defRequest(keyString.c_str());
        if (isalpha(tmpcached[0])) {
            if ((tmpcached == Cached("FIRST")) &&
                (myMap_[keyString] == 999))
                // If Default first and set is last
                drawPriorRequest(keyString.c_str()) = "LAST";
        }
        else {
            defPriorValue = defRequest(keyString.c_str());
            if (myMap_[keyString] != defPriorValue)
                // If different from default
                drawPriorRequest(keyString.c_str()) = myMap_[keyString];
        }
    }

    if (drawPriorRequest.countParameters() > 0) {
        // convert my request to macro
        std::set<Cached> skipSet;

        pageName += +"_priority";
        description.ConvertRequestToMacro(drawPriorRequest, PUT_END, pageName.c_str(), "drawing_priority", skipSet);

        return pageName;
    }
    else
        return "";
}

Cached
DrawingPriority::DrawSegmentName(int dataUnitId, MvRequest& request, int visDefId)
{
    std::ostringstream ss;
    ss << this->Priority(request)
       << "DATA"
       << std::setfill('0') << std::setw(5) << dataUnitId
       << "VISDEF";

    if (visDefId)
        ss << std::setfill('0') << std::setw(5) << visDefId;

    ss << ends;

    return {ss.str().c_str()};
}
