/***************************** 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:
//  Graphics Engine
//
// .AUTHOR:
//  Gilberto Camara, Baudoin Raoult and Fernando Ii
//
// .SUMMARY:
//  Describes the Graphics Engine class, a class for
//  handling the different drawing packages supported by PlotMod
//
//  Each page is associated to one graphics engine, so one
//  object of this class is instantiated per page.
//
//  There wil be one canvas associated with each type of graphics engine
//
// .CLIENTS:
//  Presentable::Draw (called by CreateAction::Execute and DropAction::Execute)
//
// .RESPONSABILITIES:
//
//  The Draw method will invoke the appropriate graphics engine
//  for drawing a presentable.
//
//  Each specific engine will obtain its parameters from
//  its client (the parameters are contained in a request or are
//  part of the calling Presentable).
//
//  There are four types of specialised graphics engines in PlotMod:
//
//  - DefaultGraphicsEngine, which dumps the contents of a SuperPage
//    into a file
//
//  - MagicsGraphicsEngine, which uses the MAGICS library
//
//  - DraftGraphicsEngine, which produces plot of lower quality
//    than MAGICS, but is faster
//
//  - Vis5DGraphicsEngine, which uses the Vis5D system
//
//  These graphics engines will be concrete classes derived from the
//  GraphicsEngine base class, and create by a factory.
//
// .COLLABORATORS:
//  Device, Canvas
//
// .DESCENDENT:
//  DefaultGraphicsEngine, MagicsGraphicsEngine, DraftGraphicsEngine,
//  Vis5DGraphicsEngine
//
// .REFERENCES:
//  This class is based on the "Factory" pattern (see
//  "Design Patterns" book, page 107).
//
//  The templated factory is based on the idea of "traits"
//  described in the article "A New and Useful Template Technique: "Traits"
//  by Nathan Myers, included in the "C++ Gems" book
//  (see also Stroustrup, 3rd. edition, page 580ff).
//
#pragma once

#include <Factory.hpp>
#include "MvIconDataBase.h"
#include "Canvas.h"

class Canvas;
class GraphicsEngine;
class Presentable;
class Cached;

struct GEFactoryTraits
{
    using Type = GraphicsEngine;
    using Parameter = Presentable&;
    static Cached FactoryName(Parameter);
    static Type* DefaultObject(Parameter);
};

class GraphicsEngineFactory : public Factory<GEFactoryTraits>
{
public:
    GraphicsEngineFactory(const Cached& name) :
        Factory<GEFactoryTraits>(name) {}
};

class GraphicsEngine
{
public:
    // Contructors
    GraphicsEngine(Presentable& owner);

    // Destructor
    virtual ~GraphicsEngine() = default;

#if 0
	// Constructor for Different Types of Canvas
	virtual PSCanvas * MakePSCanvas ( Device&, 
					  const Point&,
					  const Rectangle&,
					  const PaperSize&,
					  const PaperSize&,
					  int ) const = 0;

	virtual XCanvas  * MakeXCanvas ( Device&, 
					 PresentableWidget* parent,
					 const Rectangle&,
					 const PaperSize&,
					 int )  const = 0;
#endif

    virtual Canvas* MakeCanvas(Device&,
                               const Rectangle&,
                               const PaperSize&,
                               int) const = 0;

    // Methods
    virtual void StartPicture(const char*) = 0;
    virtual void EndPicture() = 0;

    virtual void DrawProlog() = 0;
    virtual void DrawPageHeader(Canvas&) = 0;
    virtual void DrawTrailer(MvRequest&) = 0;

    // Draws a dataUnit+visDef onto a canvas
    // REQUIRE: 1. dataUnit must provide a valid request, which contains
    //             information about data location
    //          2. dataUnitIndex indicates the location of the field/obs
    //             whithin the dataUnit (where applicable)
    //          3. Device must have been pre-configured
    virtual void DrawDataVisDef(MvIcon&, MvRequest&, MvIconList&, int = 0) = 0;

    // Draws a dataUnit onto a canvas
    // REQUIRE: 1. dataUnit must provide a valid request, which contains
    //             information about data location
    //          2. dataUnitIndex indicates the location of the field/obs
    //             whithin the dataUnit (where applicable)
    //          3. Device must have been pre-configured
    virtual void DrawDataUnit(MvIcon&, MvRequest&, MvIcon&) = 0;

    virtual void DrawNewPage(MvRequest&) = 0;
    virtual void Draw(const MvRequest&, bool = false) = 0;

protected:
    Presentable& owner_;  // keep track of my owner
};
