/***************************** 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:
//  Presentable
//
// .AUTHOR:
//  Gilberto Camara, Baudoiun Raoult and Fernando Ii
//
// .SUMMARY:
//  Defines an abstract base class for the page hierarchy in PlotMod.
//  The Presentable class is an example of the Composite "pattern".
//
//  Its methods allow for the insertion and removal of nodes and
//  leaves on a tree structure, and also for the drawing method.
//
//  The building of the tree structure, from a description,
//  is done by the Builder class.
//
//  Other applications that use Presentable (such as Matching) are
//  implemented by the Visitor class.
//
// .DESCRIPTION:
//  Refer to the "Design Patterns" book, page 163 for more details
//
//
// .DESCENDENT:
//  Page, SubPage, DataObject, Text, Legend
//
// .RELATED:
//  PlotMod, Builder, Visitor, Device
//
// .ASCENDENT:
//
//
#ifndef Presentable_H
#define Presentable_H

#include <inc_stl.h>

#include "MvRequest.h"
#include "MvIconDataBase.h"
#include "DeviceData.h"
#include "Visitor.h"
#include "PlotModConst.h"
#include "PaperSize.h"
#include "Location.h"
#include "MatchingInfo.h"

class PmContext;
class Canvas;
class GraphicsEngine;
class DrawingPriority;
class PlotModView;
class Presentable;
class ObjectInfo;

typedef map <string, pair<int, int> > DrawPriorMap;

typedef map<int,string> MacroVisDefMap;

enum { GETBYDATAUNIT,GETBYVISDEF};

class PresentableObserver {

   friend class Presentable;

   set <Presentable*> observed_;
   void Dead(Presentable*);

   // Override this one
   virtual void Notify(Presentable&) = 0;

public:

   void Observe(Presentable&);
   void Forget(Presentable&);

   void ForgetAll();

   virtual ~PresentableObserver();
};

class Presentable {

public:

   // Contructor
   // Builds a presentable without a request (used for data objects)
   Presentable();

   // Builds a presentable from a Request
   Presentable( const MvRequest& inRequest);

   Presentable(const Presentable&);

   virtual Presentable* Clone() const { return new Presentable(*this); }

   // Destructor
   virtual ~Presentable();

   // Members Information

   // Returns a reference to the object's associated request
   virtual MvRequest& Request() { return myRequest_; }

   // true : presentable is a window (interactive)
   // false: presentable is not a window
   virtual bool IsAWindow() { return myParent_->IsAWindow(); }

   virtual bool HasDrawTask ();
   virtual void HasDrawTask( bool yesno ) { hasDrawTask_ = yesno; }

   // Draws the presentable
   virtual void Draw ();
   virtual void DrawProlog ();
   virtual void DrawPageHeader () {}
   virtual void DrawTrailer () {}
   virtual void DrawTrailer ( MvRequest& );
   virtual void DrawTask ();    // Ask the server to draw me
   virtual bool CheckDrawTask(); // Check if there is any task to be performed

   // Methods for Inserting and Removing Children
   // Inserts a new child in the tree hierachy
   // Fails if the object is a leaf
   virtual void Insert (Presentable* p);

   // Remove an existing child from the tree hierarchy
   // Fails if the object is a leaf
   virtual void Remove (Presentable* p);

   virtual void CreateReply ( MvRequest& ) {}

   // Dealing with Drop
   virtual void Drop ( PmContext& context );
   virtual void DropSimulate ( PmContext& context );

   // Dealing with observers
   void NotifyObservers();

   // Zoom methods
   virtual void ZoomRequest ( int, const Location&  ) {}
   virtual void ZoomRequest ( int, const string&  ) {}
   virtual void ZoomRequest ( int, int  ) {}
   virtual void ZoomInfo(int&, int&) {cout << "Should not be here" << endl;}

   // Layer methods
   virtual bool UpdateLayerTransparency  ( int, int )  { return false; }
   virtual bool UpdateLayerVisibility    ( int, bool ) { return false; }
   virtual bool UpdateLayerStackingOrder ( int, int )  { return false; }

   // Dealing with Contents
   virtual string MacroPlotIndexName(bool = false) { return ""; }
   virtual void contentsRequest( MvRequest& ) {}

   virtual string Name();
   virtual string MacroName();

   // Flag indicanting if drop came from Contents Window or Macro
   virtual void DropShouldStay( bool ) { }
   virtual bool DropShouldStay() { return false; }

   virtual void ContentsDataUnit( int ) { }
   virtual int ContentsDataUnit() { return  0; }

   // Register to draw trailer later
   virtual void RegisterDrawTrailer () {}

   // Remove from tree structure, not database
   virtual void RemoveIcon ( MvIcon& ) {}
   virtual void RemoveMyData ();
   virtual void RemoveAllData () {}
   virtual void RemoveAllDataChildren ();

   // Remove icon from tree structure and database
   virtual void RemoveIcon ( const int );

   // Dealing with Macro
   // Create Macro code from the Display Window
   virtual void GenerateMacro ( ) { }

   // Generate a description of the presentable
   virtual void DescribeYourself ( ObjectInfo&   ) {}

   // Describe the drops (data units and visdefs)
   virtual void DescribeDrops ( ObjectInfo&, MacroVisDefMap& );
   virtual void DescribeDrops ( ObjectInfo&, MvRequest& );

   // Methods for Handling the Children and the Father
   const Presentable* Parent() const
      { return myParent_; }

   void Parent( Presentable* pp )
      { myParent_ = pp; }

   // Return number of children
   int NrOfChildren() const { return childList_.size(); }

   // Methods which traverse the tree hierarchy
   // Finds a sub-branch of the tree hierarchy whose
   // top node has the same ID as "treeNodeId"
   Presentable* FindBranch (const int treeNodeId) const;

   // Finds a sub-branch of the tree hierarchy whose
   // top node has a View specified by "viewName"
   Presentable* FindBranch (string viewName);

   // Finds a sub-branch of the tree hierarchy whose
   // top node has a request specified by "requestName"
   void FindBranchesByRequest(string requestName,vector<Presentable*>& presVec);

   // Finds a sub-branch of the tree hierarchy whose
   // node contains an icon specified by its Id
   Presentable* FindBranchByIconId (int, int&) const;
   int FindBranchIdByIconId (int, int&);

   // Finds the superpage associated to a presentable
   virtual Presentable* FindSuperPage () const;

   // Informs if the presentable has a dataObject
   virtual bool HasData();

   // Informs if the presentable has a child with a dataObject
   virtual bool ChildHasData();

   // Indicates that a presentable is not matched
   virtual void NotMatched() { hasMatch_ = false; }

   // Indicates that a match has been found for the presentable
   virtual void MatchFound() { hasMatch_ = true; }

   // Retrives the information about the object's matching
   virtual bool HasBeenMatched() { return hasMatch_; }

   // Initializes all of the presentables' children
   // to be un-matched (to be used in the beginning of
   // the matching procedure)
   virtual void InitMatching();

   // Indicates a reference matching info for the presentable
   virtual void SetMatchingInfo(const MatchingInfo& dataInfo)
      { matchingInfo_ = dataInfo; }

   // Retrive the matching info associated with the treeNode
   virtual const MatchingInfo& GetMatchingInfo() const
      { return matchingInfo_; }

   // Methods used for Drawing
   // Draws the presentable's children
   virtual void DrawChildren ();

   // Store the Layer info
   virtual void DrawLayerInfo ( const int, const char* name=0 );

   virtual void DrawText ( ) {}

   virtual int PageIndex();

   virtual int PaperPageIndex() const;
   virtual void PaperPageIndex ( int );

   virtual bool PrintAll () { return false; }
   virtual void PrintAll ( bool ) {}

   virtual int PaperPageNumber ( int ) { return -1; }

   virtual void DrawDataVisDef() {}

   // Retrieve all requests for the whole tree.
   // The requests have already been built and saved internally, but
   // they are not updated automatically if the layers
   // visibility/order/transparency are modified by the uPlot Sidebar.
   // Boolean checkIconStatus = false means use the saved requests;
   // otherwise, rebuild the requests by analysing the whole tree.
   virtual void GetAllRequests( MvRequest&, bool checkIconStatus=false );

//   virtual void EraseDraw ( int  = 0 ) {}
//   virtual void EraseDefaultDraw ();

   // Methods which access the MvIconDataBase
   // This method is used to retrieve a valid visdef. It is called when
   // there are no visual definitions associated to a data unit. If last
   // arg is GETBYDATAUNIT, the first arg is interpreted as a dataunit class.
   // If last arg is GETBYVISDEF, first arg is the visdef class to retrive.
   virtual bool DefaultVisDefList (const char*, MvIconList&, int ndimflag = 0, int type = GETBYDATAUNIT);

   // Overridden by Page/SubPage
   virtual bool CheckValidVisDef(MvIcon&, MvRequest&)
      { return true; }

   // Retrieve icons/number of icons related to a Layer
   virtual bool RetrieveIconsFromLayer( int, MvIconList& );
   virtual int RetrieveNumberIconsFromLayer( int );

   // Retrieve the Texts associated to the node
   virtual bool RetrieveTextList ( MvIconList& );
   virtual bool RetrieveTextTitle ( MvIconList& );
   virtual void RetrieveTextAnnotation ( MvIconList& );

   // Retrieve the Legend associated to the tree
   virtual bool RetrieveLegend ( MvIcon& );

   // Retrieve the Import list associated to the node
   // Returns false if there are no Import icons.
   virtual bool RetrieveImportList ( MvIconList& );

   // Retrieves the icon database associated to the
   // tree branch (normally, a superpage)
   virtual MvIconDataBase& IconDataBase() const
      { return myParent_->IconDataBase(); }

   // Retrieve data unit info
   void GetDataUnitInfo ( MvRequest& );

   //  Dealing with Devices and GraphicsEngine
   virtual GraphicsEngine& GetGraphicsEngine() const;
   virtual PlotModView& GetView() const;

   // Dealing with Canvas
   virtual Canvas& GetCanvas() const ;
   virtual void    SetCanvas ( Canvas * ) {}
   virtual bool    HasCanvas() { return false; }

   // Dealing with Printing
   virtual void PendingDrawingsAdd();
   virtual void PendingDrawingsRemove();
   virtual bool PendingDrawings()
      { return  (  pendingDrawings_ != 0 ); }

   virtual void HasReceivedNewpage( bool flag)
      { hasNewpage_ = flag; }

   virtual bool HasReceivedNewpage()
      { return hasNewpage_; }

   // Dealing with DeviceData
   DeviceData* ReleaseDeviceData ( );
   void        SetDeviceData ( DeviceData* devdata );
   DeviceData* GetDeviceData() const { return deviceData_.get(); }

   virtual void Visit ( Visitor& v ) { VisitChildren ( v ); }

   void VisitChildren ( Visitor& v );

   // Set/Get the location for the presentable
   virtual void SetLocation ( Location pos ) { myLocation_ = pos; }

   Rectangle GetLocation ( ) { return myLocation_; }

   // Members and Object Information
   // true : presentable is visible and will be drawn
   // false: presentable is not visible
   virtual bool IsVisible() { return isVisible_; }

   // Set the visibility for the presentable
   virtual void SetVisibility ( bool visibility )
      { isVisible_ = visibility; }

   // Returns the object's unique identification
   int Id() const { return presentableId_ ; }

   virtual long PictureId(const char *, bool = false)
      { return 0; }

   virtual PaperSize GetChildSize ( Presentable& );

   virtual PaperSize GetMySize()
      { return myParent_->GetChildSize ( *this ); }

   virtual void NeedsRedrawing(bool yesno)
      { needsRedrawing_ = yesno; }

   virtual bool NeedsRedrawing() { return  needsRedrawing_; }

   // Set the projection associated to the canvas
   virtual void SetProjection ( const MvRequest& ) {}

   virtual bool CanDoZoom() { return false; }

   virtual void SetDrawPriority( MvRequest& ) {}

   virtual DrawingPriority& GetDrawPriority ();

   // Indicate//determine whether a page is visited in background
   virtual bool VisitInBackground() { return false; }
   virtual void VisitInBackground(bool ) {}

   virtual bool RemoveData() { return removeData_; }

   virtual void RemoveData( bool yesno ) { removeData_ = yesno; }

   // Used to indicate Contents drop on a window
   bool DroppedHere () { return droppedHere_; }
   void DroppedHere ( int Id ) { droppedHere_ = ( Id == presentableId_ ); }

   // Insert icons to the database
   virtual bool InsertCommonIcons ( const MvRequest& );
   virtual Page* InsertOnePage ( MvRequest& )
      { cout << "Should not be here" << endl; return 0; }

   // Sets redrawing flags and does AddTask if needed
   virtual void RedrawIfWindow(int = 0) {}

   virtual void DataUnit(MvIcon&) {}

   // Dealing with Export plotting
   virtual bool ExportPlot ( MvRequest*, bool = false ) { return false; }
   virtual MvRequest ExportToEcCharts () { return MvRequest(); }

   // Dealing with Print plotting
   virtual void PrintFile ( MvRequest& ) { }

   virtual void SetRequest(const MvRequest & );

   // Dealing with rebuilding the visualization tree
   void Refresh ( bool refresh ) { refresh_ = refresh; }
   bool Refresh () { return refresh_; }

   // Handle Coastlines icon
   // Provide coastline information
   virtual void ProcessCoastlines ( MvRequest&, bool, bool foundDU=false );

   // Split icon coastlines into background and foreground coastlines
   virtual void SplitCoastlines(MvRequest&, MvRequest&, MvRequest&);

   // Build a coastline background/foreground icon derived from a coastline icon
   virtual void CoastlinesBackground(MvRequest&, MvRequest&);
   virtual void CoastlinesForeground(MvRequest&, MvRequest&);

protected:

   bool DescribeVisDefList( ObjectInfo&, MvIconList&, MvIcon&, string&, bool, MacroVisDefMap& );

   // Members
   static int treeNodeCounter_;        // used to obtain unique Id
   MvRequest myRequest_;               // request used to build me
   int presentableId_;                 // unique Id
   Presentable* myParent_;             // next level up on the tree
   auto_ptr <DeviceData > deviceData_; // information on the device
   Location myLocation_;               // position of the presentable

   // Definition for the tree hierarchy of the Presentable class
   typedef list <Presentable* > MvChildList;
   typedef list <Presentable* >::iterator MvChildIterator;
   typedef list <Presentable* >::const_iterator MvChildConstIterator;

   MvChildList childList_;     // list of children
   bool hasMatch_;             // indicates that a object has been matched
   MatchingInfo matchingInfo_; // matching information

   bool isVisible_;            // indicates if the presentable is visible

   bool hasNewpage_;           // indicates if the presentable
                               // has received a newpage directive

   int pendingDrawings_;       // number of pending drawings
   bool needsRedrawing_;       // Needed when scrolling to find out
                               // if presentable needs redrawing

   bool removeData_;           // To be used when removing icons
                               // True if data is to be removed
                               // False removes data drawing only

   bool hasDrawTask_;          // Used to indicate if the presentable
                               // has been put in the Task list to be drawn

   bool droppedHere_;          // indicates if Contents Drop was
                               // done in this window

   bool refresh_;              // tag to rebuild/not the visualization tree

private:

   // No copy allowed
   Presentable& operator=(const Presentable&);

   // Observer
   set<PresentableObserver*> observers_;

   friend class PresentableObserver;

   void Add(PresentableObserver*);
   void Remove(PresentableObserver*);
};

#endif
