/***************************** 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:
//  PlotModView
//
// .AUTHOR:
//  Gilberto Camara, Baudoin Raoult and Fernando Ii
//
// .SUMMARY:
//  Describes the PlotModView class, a base class
//  for the various types of views in PlotMod
//
//  There is one view per page and the view is responsible
//  for providing the page with the matching information
//
//
// .CLIENTS:
//  CreateAction, DropAction
//
// .RESPONSIBILITY:
//
//  - For a page already with data, inform if two
//    matching information are compatible
//
//
// .COLLABORATORS:
//  ObjectList - extracts information from the request
//  MatchingCriteria - verify compatibility of data
//
// .ASCENDENT:
//
//
// .DESCENDENT:
//  MapView
//
// .REFERENCES:
//
//  The design of this class is based on the "Factory" pattern
//  ("Design Patterns", page. 107)
//
//
#pragma once

#include <functional>
#include <map>
#include <string>

#include <Cached.h>
#include <MvRequest.h>

#include "Presentable.h"
#include "MatchingCriteria.h"

class PlotModView;
class Page;

class PlotModViewFactory
{
protected:
    using FactoryMap = std::map<Cached, PlotModViewFactory*, std::less<Cached>>;
    static FactoryMap* factoryMap_;
    Cached name_;

    virtual PlotModView* Build(Page&, const MvRequest&, const MvRequest&) = 0;

public:
    // Normal Constructor
    PlotModViewFactory(const Cached& decoderName);

    // Virtual Constructor
    static PlotModView* Make(Page&, MvRequest& viewRequest);

    // Keep compiler happy
    virtual ~PlotModViewFactory() = default;
};

class PlotModView
{
public:
    // Contructor
    PlotModView(Page&, const MvRequest&, const MvRequest&);
    PlotModView(const PlotModView& old);
    virtual PlotModView* Clone() const = 0;

    // Destructor
    virtual ~PlotModView();

    // Get the object name
    virtual std::string Name() = 0;

    virtual std::string MacroName();

    virtual Page& Owner() { return *owner_; }
    virtual void Owner(Page& xx);

    // Overridden by views that needs to call an application.
    virtual bool CallService(const MvRequest&, PmContext&)
    {
        return false;
    }

    // Verify if matching is possible
    virtual bool Match(const MatchingInfo& lhs, const MatchingInfo& rhs) const;

    // Delete all data and drop it to PlotMod again
    virtual void RecreateData();

    // Get a visdef from the database matching the fields in the given request
    virtual bool GetVisDef(Presentable&, const MvRequest&, MvIconList&);

    // -- Methods which are overriden by derived classes

    // Process the drop
    virtual void Drop(PmContext& context) = 0;

    // Dealing with Contents tools
    virtual void contentsRequest(MvRequest&);

    // Retrieves a list of visdefs
    virtual bool RetrieveVisdefList(MvRequest& dropReq, MvRequest& vdReqList);

    // Insert a new data request into the page hierarchy
    virtual MvIconList InsertDataRequest(MvRequest& dropRequest) = 0;

    // Decode the data unit
    virtual void DecodeDataUnit(MvIcon&) = 0;

    // Replace the current view depending on the type of the view
    virtual bool UpdateView() { return true; }

    // Replace the current geographical area
    // virtual void ReplaceArea ( const Location&, int /* izoom=-1 */ ) {}

    // Sets up the drawing area
    virtual void DrawNewPage();

    virtual void DrawBackground() = 0;

    // Draw the foreground (coastlines or axis )
    virtual void DrawForeground() = 0;

    virtual void Draw(SubPage*);

    virtual void CommonDraw(SubPage*, DrawPriorMap&);

    // Describe the contents of the view
    virtual void DescribeYourself(ObjectInfo&) = 0;

    virtual MvRequest& ViewRequest()
    {
        return viewRequest_;
    }

    virtual void ViewRequest(const MvRequest& viewReq)
    {
        viewRequest_ = viewReq;
    }

    void ParentDataUnitId(int parentDataUnitId)
    {
        viewRequest_("_PARENT_DATAUNIT_ID") = parentDataUnitId;
        parentDataUnitId_ = parentDataUnitId;
    }

    int ParentDataUnitId() { return parentDataUnitId_; }

    virtual bool BackgroundFromData() const
    {
        return false;
    }

    // Overridden by derived classes if they need to do something when things are removed from contents
    virtual bool Reset(const MvRequest&)
    {
        return false;
    }

    // Zoom inquiry
    virtual bool CanDoZoom() { return true; }

    // Check consistency between the View and Data Module
    virtual bool ConsistencyCheck(MvRequest&, MvRequest&) { return true; }

protected:
    Page* owner_;
    MvRequest viewRequest_;
    MatchingCriteria matchingCriteria_;
    int pageId_;
    int parentDataUnitId_;
};
