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

// File PlotModBuilder
// Gilberto Camara - ECMWF Apr 97
//
//

#include "PlotPageBuilder.h"

#include <Assertions.hpp>
#include "ObjectList.h"
#include "Page.h"
#include "PmContext.h"
#include "Root.h"
#include "SuperPage.h"

// This is the singleton instance of the prototype
static PlotPageBuilder plotpageBuilderInstance("PlotPageBuilder");

//
//   Methods for the PlotPageBuilder  class
//

PlotPageBuilder&
PlotPageBuilder::Instance()
{
    return plotpageBuilderInstance;
}

Presentable*
PlotPageBuilder::Execute(PmContext& context)
{
    // Creation of a new PlotPage and associated pages
    // Check if request is a PLOTSUPERPAGE
    MvRequest contextReq = context.InRequest();

    const char* verb = contextReq.getVerb();
    Presentable* superpage = nullptr;
    MvRequest defaultSuperPage;

    // Flag to indicate that the current request was not used to build the
    // SUPERPAGE. So it will need to be handle by the DropSimulate function.
    // Examples of such requests are: MCOAST, MCONT, ...
    bool skipReq = true;

    // Build a PLOTSUPERPAGE. If the superpage structure
    // already exists, only add the new page
    if (verb == PLOTSUPERPAGE) {
        superpage = Root::Instance().FindSuperPage();
        if (superpage) {
            // Insert Page
            Page* page = superpage->InsertOnePage(contextReq);

            context.Advance();  // Skip request processed above

            // Deal with further requests
            page->DropSimulate(context);

            return superpage;
        }
        // for efficiency, only copy the portion of the request that we will need
        MvRequest nextReq;
        nextReq.copyFromCurrentTo(context.InRequest(), NEWPAGE.c_str());

        superpage = new SuperPage(nextReq);
    }
    else  // build a default PLOTSUPERPAGE (to deal with MAPVIEW,...)
    {
        // Check internal parameter _NAME . It may be used later (e.g. automatic macro generation)
        const char* fullName = (const char*)contextReq("_NAME");
        const char* path = nullptr;
        if (fullName)
            path = mdirname(fullName);

        defaultSuperPage = ObjectList::CreateDefaultRequest("PLOT_SUPERPAGE", 0, path);

        // Update Pages info
        if (strcmp(verb, PLOTPAGE) == 0)
            defaultSuperPage("PAGES") = context.InRequest();
        else if (ObjectList::IsView(verb))  // View
        {
            // Create default page and add view to this request.
            MvRequest pageRequest = ObjectList::CreateDefaultRequest("PLOT_PAGE");
            pageRequest("VIEW") = contextReq.justOneRequest();
            defaultSuperPage("PAGES") = pageRequest;
        }

        // If there is a data unit, we try to build a view according to this.
        // Else a default superpage with nothing in it will be built.
        else if (ObjectList::IsDataUnit(verb) || ObjectList::IsVisDef(verb)) {
            MvRequest pageRequest = ObjectList::CreateDefaultRequest("PLOT_PAGE");

            Cached viewName = GetView(context);
            if ((const char*)viewName) {
                MvRequest viewRequest = ObjectList::CreateDefaultRequest(viewName);
                pageRequest("VIEW") = viewRequest;
            }

            defaultSuperPage("PAGES") = pageRequest;
            skipReq = false;
        }
        else
            skipReq = false;

        superpage = new SuperPage(defaultSuperPage);
    }

    ensure(superpage != nullptr);

    // Put the new branch in the tree
    Root::Instance().Insert(superpage);

    // Add the page Ids in the reply
    // Create a Reply
    MvRequest reply;
    superpage->CreateReply(reply);
    context.AddToReply(reply);

    if (skipReq)
        context.Advance();  // Skip request processed above

    // Deal with further requests
    superpage->DropSimulate(context);

    return superpage;
}
