/***************************** 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:
//  PmContext
//
// .AUTHOR:
//  Gilberto Camara, Baudouin Raoult and Fernando Ii
//
// .SUMMARY:
//  Defines a context for the execution of actions in PlotMod.
//  The context is the object which is used to control the
//  processing of a request in PlotMod.
//
//  A context is created based on an MvProtocol and an input MvRequest.
//  For each new action which processes part of the input request,
//  the context is updated (by advancing to the next request).
//
//  PmContext is a "reference counted" class, to increase efficiency
//  and avoid unecessary copying. As such, it is derived from "Counted" (q.v.)
//
// .CLIENTS:
//  PlotModApp, PlotModAction, PlotModView, PlotModTask
//
//
// .RESPONSABILITIES:
//  1. Call the necessary actions for processing a request
//  2. Keep track of which requests have been processed
//  3. Advance to the next input request after the current
//     request has been processed
//  4. Provide indication of progress and errors
//
// .COLLABORATORS:
//  PlotModAction
//
//
// .BASE CLASS:
//  Counted
//
// .DERIVED CLASSES:
//
//
// .REFERENCES:
//
//
#pragma once

#include "MvRequest.h"
#include "Counted.h"

class MvProtocol;

class PmContext : public Counted
{
public:
    // Contructors
    // Builds a context from a protocol and an input request
    PmContext(MvProtocol& proto, const MvRequest& inRequest);

    //  Methods
    // Indicate progress
    std::ostream& Progress();

    // Indicate error
    std::ostream& Error();

    // Add this request to the reply request
    void AddToReply(const MvRequest&);

    // Set the presentable
    // void SetCurrentPresentable ( Presentable* );

    // Find out the current presentable
    // Presentable* GetCurrentPresentable ( );

    // Execute the request
    void Execute();

    // Advance to the next request
    void Advance() { inRequest_.advance(); }

    // Advance to the next verb request
    void AdvanceTo(std::string& v) { inRequest_.advanceTo(v); }

    // Advance to the next verb request
    void AdvanceAfter(std::string& v) { inRequest_.advanceAfter(v); }

    // Advance to the end of all requests
    void AdvanceToEnd() { inRequest_.advanceToEnd(); }

    // Rewind and advance to the next request after DROP request
    void RewindToAfterDrop();

    // Return the input request
    const MvRequest& InRequest();

    // Return the verb of the first data unit found in input request.
    Cached FirstDataView() { return firstDataView_; }
    void FirstDataView(Cached xx) { firstDataView_ = xx; }

    // Give the clients the option of updating the inRequest, either to massage
    // it to add fields for helping macro generation, or for removing requests
    // that has been processed.
    void Update(const MvRequest& changedReq) { inRequest_ = changedReq; }

    void DropX(double x) { dropX_ = x; }
    double DropX() { return dropX_; }

    void DropY(double y) { dropY_ = y; }
    double DropY() { return dropY_; }

protected:
    // Destructor
    ~PmContext() override;

private:
    // No copy allowed
    PmContext(const PmContext&);
    PmContext& operator=(const PmContext&) { return *this; }

    MvRequest inRequest_;
    MvRequest outRequest_;

    MvProtocol& proto_;

    // Presentable* presentable_;

    Cached firstDataView_;

    double dropX_{0.};
    double dropY_{0.};
};
