/***************************** 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 MvIconDataBase
// Gilberto Camara - ECMWF Jun 97
//
// .NAME:	
//  MvIconDataBase
//
// .AUTHOR:
//  Gilberto Camara and Fernando Ii
//
// .SUMMARY:
//  Implements a data base of Data Units and VisDefs
//  and a m:n relation between a DataUnit and a VisDef
//
// .CLIENTS:
//  Presentable
//
// .RESPONSABILITIES:
//  - Store the dataunits and visdef, 
//  - Retrieve them based on a key (Id) or an icon name
//  - Given a DataUnit, retrieve the corresponding VisDef
//
// .COLLABORATORS:
//  MvIcon, STL classes (list, multimap)
//
// .BASE CLASS:
//
// .DERIVED CLASSES:
//
// .REFERENCES:
//
#ifndef MvIconDataBase_H
#define MvIconDataBase_H

#include <inc_iostream.h>

#include "MvIcon.h"

// Relation types
enum { PRES_DATAUNIT_REL, PRES_VISDEF_REL, PRES_TEXT_REL, PRES_LEGEND_REL, ICON_LAYER_REL, DATAUNIT_VISDEF_REL, PRES_IMPORT_REL, PRES_LAYER_REL };

// Icon list types
enum { DB_DATAUNIT, DB_VISDEF, DB_TEXT, DB_LEGEND, DB_LAYER, DB_IMPORT };

//  Definitions for the Icon List
typedef list <MvIcon> MvIconList;

//  Definitions for the Link List
typedef list <string> MvLinkList;

// Definitions of the iterators that will loop through the lists
typedef MvIconList::iterator MvListCursor;

// Definition for a relation to store m:n relationships
typedef multimap <int, int> MvRelation;

// Definition for the pairs of entries in the relation 
typedef MvRelation::value_type MvEntryPair;

// Definition for the iterator that loops through the relation pairs
typedef MvRelation::iterator MvRelationCursor;

// Definition for a relation to store m relationships
typedef map <int, MvIconList> MvMapRelation;

// Definition for the pairs of entries in the MvMapRelation
typedef MvMapRelation::value_type MvMapEntryPair;

// Definition for the iterator that loops through the MvMapRelation pairs
typedef MvMapRelation::iterator MvMapRelationCursor;

class MvIconDataBase {

public:

   // Contructors
   MvIconDataBase() {};
   MvIconDataBase(const MvIconDataBase&);

   // Destructor
   ~MvIconDataBase();

//---------------------------------------------
// --- Methods for the Data Unit
//---------------------------------------------

   // Inserts a new DataUnit into the DataUnit List
   bool InsertDataUnit ( MvIcon& newDataUnit, int presentableId = 0);

   // Retrieves current data unit (if not at end) and sets pointer to the next data
   bool NextDataUnit ( MvIcon& theDataUnit );


//---------------------------------------------
// --- Methods for the VisDef
//---------------------------------------------

   // Inserts a new VisDef into the VisDef List
   bool InsertVisDef   ( MvIcon& newVisDef);


//---------------------------------------------
// --- Methods for the Layer list
//---------------------------------------------

    bool UpdateLayerTransparency  ( int, int );
    bool UpdateLayerVisibility    ( int, bool );
    bool UpdateLayerStackingOrder ( );
    int  LayerIndex () { return layerList_.size(); }


//---------------------------------------------
// --- Methods for the DataUnit-VisDef Relation
//---------------------------------------------

	// Rewinds the cursor
	void DataUnitVisDefRelationRewind()
	     { duvdRelationCursor_ = dataUnitVisDefRelation_.begin(); }

	// Retrieves the next VisDef, from the current cursor position,
	// given a Data Unit ID
	bool NextVisDefByDataUnitId (const int dataunitId, MvIcon& theVisDef);

//       bool DataUnitHasVisDef(const int dataUnitId,const int visdefId);
       // Find out if a dataunit has visdef with the given id.

	// Retrieve all visdefs associated a data unit
	bool RetrieveVisDefList ( const MvIcon& dataUnit, MvIconList& visdefList );

//	bool RetrieveDataUnitFromVisDef ( const int visdefId, MvIcon& theDataUnit);
	// Retrieve data unit given a visdef Id

//	void RetrieveVisDefList ( MvIconList& dataUnitList, MvIconList& visdefList );
	// Retrieve all visdefs associated to a data unit list

	// Remove all visdefs associated to a data unit
	bool RemoveAllVisDefsByDataUnit( MvIcon& dataUnit, const MvRequest* vd = 0 );

	// Remove all visdefs associated to a data unit list
	// according to its class (if defined)
	void RemoveAllVisDefsByDataUnitList ( MvIconList& dataUnitList, const MvRequest* vd = 0 );

	// Remove Data Unit from the database
	void RemoveDataUnit ( MvIcon& theDataUnit );

	// Remove all Data Units, associated with a specific
	// presentable Id, from the database
	void RemoveDataUnit ( const int presentableId );

	// Remove all Data Units from the database
	void RemoveDataUnit ( );

//	void RemoveVisDef ( MvIcon& theVisDef );
	// Remove Visdef from the database

	// Remove all VisDefs, associated with a specific
	// presentable Id and for a given class (if presente),
	// from the database
	void RemoveVisDef ( const int presentableId, const MvRequest* vd=0 );

	// Remove all VisDefs  from the database
	void RemoveVisDef ( );

//	int UpdateVisDefByName (const MvRequest& visdefRequest, const MvIcon& duIcon);
	// Updates visdef given its name. Returns the Id of the VisDef updated.


//--------------------------------------------------
// --- Methods for the Presentable-VisDef Relation
//--------------------------------------------------

	// Rewinds the cursor
	void PresentableVisDefRelationRewind()
	     { prvdRelationCursor_ = presentableVisDefRelation_.begin(); }

	// Retrieves the next VisDef, from the current cursor position,
	// given a Presentable Id
	bool NextVisDefByPresentableId (const int presentableId, MvIcon& theVisDef);

	// Retrieve the visdef list associated to a data unit and a presentable
	bool VisDefListByDataUnitAndPresentableId ( const int presentableId, const char* dataUnitName, MvIconList& visdefList );

	// Retrieve the visdef list associated to a presentable
	//bool VisDefListByPresentableId ( const int presentableId, MvIconList& visdefList );

//	void UpdatePresentableVisDefRelation ( const int newPresentableId, const int oldPresentableId );
	// Update Presentable-VisDef Relation with a new Presentable Id

	// Remove VisDefs associated to a presentable, given a
	// certain class (if selected)
	void RemoveVisDefFromPresRel ( const int presentableId, const MvRequest* vd = 0 );


//--------------------------------------------------
// --- Methods for the Presentable-DataUnit Relation
//--------------------------------------------------

	// Rewinds the cursor
	void PresentableDataUnitRelationRewind()
		{ prduRelationCursor_ = presentableDataUnitRelation_.begin(); }

	// Retrieves the next DataUnit, from the current cursor position,
	// given a Presentable Id
	bool NextDataUnitByPresentableId (const int presentableId, MvIcon& theVisDef);

	// Retrieve the dataunit list associated to a presentable
	//bool DataUnitListByPresentableId ( const int presentableId, MvIconList& dataUnitList );

	// Verify if there is any DataUnit related to the Presentable Id
	bool PresentableHasData ( const int presentableId );

//	void UpdatePresentableDataUnitRelation ( const int newPresentableId, const int oldPresentableId );
	// Update Presentable-DataUnit Relation with a new Presentable Id


//--------------------------------------------------------
// --- Methods which apply to both the Presentable-VisDef
//     and Presentable-DataUnit Relations
//--------------------------------------------------------

	// Removes all data units, given an Id
	bool RemoveAllDataUnitsFromPresRel ( MvIcon& theDataUnit );

	// Removes Presentable-DataUnit Relation given the identification
	bool RemoveDataUnitFromPresRel ( MvIcon& theDataUnit, int presentableId);

//        void UpdatePresentable ( const int newPresentableId, const int oldPresentableId );

	//  Removes all entries which are related to the presentable
	void RemovePresentable(const int PresentableId);

//--------------------------------------------------
// --- Method for dealing with dataRequests
//--------------------------------------------------

	// Includes dataunits from a request
    MvIcon InsertDataUnit ( const MvRequest& inRequest, int presentableId = 0, int index = -1 );
	
	// Inserts a visdef
	MvIcon InsertVisDef ( const MvRequest& visdefRequest, const int nodeId, MvIcon& dataUnit );

	void InsertVisDef ( MvIcon& visdef, const int nodeId );

//--------------------------------------------------
// --- General methods
//--------------------------------------------------

	// Removes all data (DataUnit,VisDef,PText)
	void RemoveAllData ( );

	// Removes all data (DataUnit,VisDef,PText) by presentable ID
//	void RemovePresentable ( const int presentableId );

    // Prints the Data Base contents
    void Print ( );

//-----------------------------------------------------------------
// --- General methods to retrieve, remove, update and insert info
//-----------------------------------------------------------------

    // Retrieve one icon giving a relation id
    bool RetrieveIcon ( const int, const int, MvIcon& );

    // Retrive all icons related to a giving relation id
    int RetrieveIcon ( const int, const int, MvIconList& );

    // Retrieve an icon from its list giving an id
    bool RetrieveIconFromList ( const int, const int, MvIcon& );

    // Retrieve all Layers related to a giving presentable id
    int RetrieveLayerIcon ( const int, MvIconList& );
    int RetrieveLayerIcon1 ( const int,MvIconList&);

    // Get icon list
    MvIconList* IconList ( const int );

    // Insert an icon (relation, list and layer) giving a relation id
    void InsertIcon ( const int, const int, MvIcon&, bool, const int = -1 );

    // Insert an icon (relation and list) giving a relation id.
    // index = position in the tree (-1 = add it in the end but before foreground)
    // exclusive = false: add it to the list
    //             true : delete the existing icons and then insert it
    void InsertIcon ( const int, const int, MvIcon&, const int index = -1, bool exclusive = false );

    // Insert a Text icon (relation and list) giving a relation id (presentable id)
    // index = position in the tree (-1 = add it into the end but before foreground)
    // This function is particular to insert icons of type Text because:
    // a) if parameter TEXT_MODE = TITLE then only one instance is allowed, i.e.,
    //    replace the existing icon.
    // b) otherwise, add this icon to the plot engine (multiple texts)
    void InsertIconText ( const int, MvIcon&, const int index = -1 );

    // Insert an icon to its list
    void InsertIcon ( const int, const MvIcon&, const int );

    // Insert a relation-icon entry
    void InsertIconRelation ( const int, const int, const int );

    // Insert the layer icon
    void InsertLayerIcon( const int, MvIcon&, int );

    // Check if icon exists
    bool CheckIcon( const int, const int );

    // Remove all icons from the database given a relation type
    void RemoveIcon ( const int );

    // Remove icon(s) from the database given a relation type and id.
    // If a iconId is also given then only that icon will be removed.
    void RemoveIcon ( const int, const int, const int iconId = -1 );

    // Remove an icon from its list giving an id
    void RemoveIconFromList (  const int, const int );

    // Removes all icons from the icons pair relation
    bool RemoveIconFromRel ( const int, const int );

    // Updates the icon request, given its unique Id
    bool UpdateIcon ( const int, const int, const MvRequest& );

private:

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

    // Utility functions for adding icons only if they do not already exist
    bool InsertIfNew(MvIcon &, MvIconList&, MvRelation& relation, int relationId = 0);
    void RelationInsertIfNew (MvRelation &relation, const int firstId, const int secondId);
    bool ExistsInRelation (MvRelation &relation, const int firstId, const int secondId);

    // All the data links are created by CreateLink routine and they
    // will be removed by calling DeleteLink in the Destructor
    void CreateLink ( MvRequest& );
    void DeleteLink ( );

    // Utility functions for handling Relations and Lists
    MvRelation* IconRelation( const int );
    int IconType ( const int );

    // Members
    // Definitions for the objects lists
    MvIconList   dataunitList_,
                 visdefList_,
                 textList_,
                 legendList_,
                 layerList_,
                 importList_;

    // Definitions for the DataUnit - VisDef pairs
    // Each DataUnit may be related to one or more VisDefs
    MvRelation       dataUnitVisDefRelation_;
    MvRelationCursor duvdRelationCursor_;

    // Definition for the Presentable - VisDef Relation
    MvRelation       presentableVisDefRelation_;
    MvRelationCursor prvdRelationCursor_;

    // Definition for the Presentable - DataUnit Relation
    MvRelation       presentableDataUnitRelation_;
    MvRelationCursor prduRelationCursor_;

    // Definition for the Presentable - PText Relation
    MvRelation presentableTextRelation_;

    // Definition for the Presentable - Legend Relation
    MvRelation presentableLegendRelation_;

    // Definition for the Presentable - Layer Relation
    MvMapRelation presentableLayerRelation_;

    // Definition for the Presentable - Import Relation
    MvRelation presentableImportRelation_;

    // Definition for the Layer - Icon Relation
    MvRelation iconLayerRelation_;

    // List of dataunit links
    MvLinkList linkList_;
};

#endif
