/***************************************************************************
 *   Copyright (C) 2005 by Thierry CHARLES   *
 *   thierry@les-charles.net   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#ifndef _PARSER_RES_H_
#define _PARSER_RES_H_

#include "components/framework/tapplication.h"
#include "components/framework/threadhandler.h"
#include "lib/lib_string.h"
#include "lib/commons.h"

#include <set>
#include <map>

DECLARE_EVENT_TYPE(EVENT_FILEPARSERRES_SYNC, -1);

class EditorPanelElement;
class ParsingThread;
class FileInfo;

class FileParserResListener;

class FileParserRes : public TApplicationRessource, protected ThreadHandler, protected wxEvtHandler
{

    public:
        FileParserRes() : thread(NULL) {this->initEvtHandler();}
        virtual ~FileParserRes();

        /** d�marre le thread de parsing */
        void startParser();
        /** pause le thread de parsing */
        void pauseParser();
        /** relance le thread de parsing */
        void continueParser();
        /** arr�te le thread de parsing */
        void stopParser();
        /** indique si le thread a �t� d�marr� */
        bool isParserRunning();
        /** indique si le thread a �t� d�marr� mais mis en pause */
        bool isParserPaused();

        /** ajoute un �couteur de modifs d'infos des fichiers */
        bool addListener(FileParserResListener * l);
        /** supprime un �couteur de modifs d'infos des fichiers */
        bool removeListener(FileParserResListener * l);
        /** dispatche un �v�nement aux �couteurs de modifs */
        void fireFileInfoUpdated(FileInfo * file);

        /**
         * renvoie les information concernant un fichier et les verrouille pour �viter toute lib�ration m�moire inopin�e
         * @param bCreateUnexistant cr�er l'entit� relative au fichier si elle n'existe pas
         * @return NULL si aucune info sur ce fichier n'existe
         * @see releaseLock()
         */
        FileInfo * getFileInfoLock(const wxString & _sFileName, bool bCreateUnexistant = true);
        /**
         * renvoie les information concernant un fichier et les verrouille pour �viter toute lib�ration m�moire inopin�e
         * @return NULL si aucune info sur ce fichier n'existe
         * @see releaseLock()
         */
        FileInfo * getFileInfoLock(const int iEditorId);
        /**
         * d�v�rouille un fichier v�rouill� pr�alablement par getFileInfoLock().
         * Il est n�cessaire de lib�rer un fichier autant de fois qu'on l'a lock�
         * @return true si le fichier n'est plus lock�
         */
        bool releaseLock(FileInfo * info);

        /** mets a jours les infos concernant un fichier avec le contenu de celles pass�es en param�tre */
        void updateFileInfo(const FileInfo * info);

        /**
         * mets a jour les informations concernant le fichier en cours de modification dans l'�diteur mentionn�
         * (ajout d'un editeur, suppression d'un �diteur, changement de nom de fichier)
         */
        void updateEditorInfo(const int iEditorId);

        /** scanne un fichier (si n�cessaire) sans le passer par la file de traitement ni par le thread */
        void requestImmediateScan(const wxString & _sFileName);

        /** scanne le contenu d'un �diteur (si n�cessaire) sans le passer par la file de traitement ni par le thread */
        void requestImmediateScan(const int iEditorId);

        /** recup�re la liste compl�te des inclusions et sous inclusions pour un editeur */
        TStringSet getFullDependanciesList(int iEditorId);

        /** �cris toutes les entr�es dans le cache */
        void dumpAll();

        /** renvoie l'id de l'�diteur qui est actuellement au premier plan */
        int getCurrentEditorId();

        /** decharge la ressource */
        virtual void prepareRessourceUnload();


    protected:
        /**
         * recherche les fichiers pour lesquels des infos sont stock�es en m�moire alors que ce n'est
         * plus n�cessaire et �cris ces informations dans le cache sur support persistant
         */
        void dumpUnusedInfos();

        /** cr�e une instance d'info pour un fichier donn� */
        virtual FileInfo * createInfoFor(const wxString & _sFileName) = 0;

        /** cr�e une instance d'info pour un editeur donn� */
        virtual FileInfo * createInfoFor(int iEditor) = 0;

        /** indique si on doit g�rer ce type d'�diteur */
        virtual bool mightHandleEditor(EditorPanelElement * editor) = 0;

        /** arrete le thread le plus vite possible. Cette m�thode est appell�e a la fermeture de l'application avant que WX ne commence la lib�ration de ses donn�es sur les thread et en rende l'arret impossible. L'objet thread devrait �tre d�truit �galement ! */
        virtual void haltThread();

        /** gestionnaire d'evenement pour r�cup�rer des infos du thread principal de maniere synchrone */
        void onEventSync( wxCommandEvent &event );

        /** scanne le contenu r�f�renc� par un objet d'info sans le passer par la file de traitement ni par le thread */
        void requestImmediateScan(FileInfo * info);

        wxCriticalSection csDataSync; // CS d'acc�s au r�cup�rateur de donn�es de mani�re synchrone
        wxCriticalSection csDataSync2; // CS d'acc�s au r�cup�rateur de donn�es de mani�re synchrone

    private:
        void initEvtHandler();
        void terminateEvtHandler();

        /**
         * recherche les fichiers pour lesquels des infos sont stock�es en m�moire alors que ce n'est
         * plus n�cessaire et �cris ces informations dans le cache sur support persistant
         * Ne g�re pas la synchro sur lock
         */
        void _dumpUnusedInfos();
        /** supprime les infos concernant un fichier de la m�moire et supprime l'�l�ment pass� en parametre */
        void removeFileInfo(FileInfo * info);
        /**
         * recup�re la liste compl�te des inclusions et sous inclusions pour un editeur
         * Ne g�re pas la synchro sur lock
         */
        TStringSet _getFullDependanciesList(int iEditorId);
        /**
         * renvoie les information concernant un fichier
         * @param bLock indique si il faut locker le fichier
         * @param bCreateUnexistant cr�er l'entit� relative au fichier si elle n'existe pas
         * @return NULL si aucune info sur ce fichier n'existe
         */
        FileInfo * _getFileInfo(const wxString & _sFileName, bool bLock, bool bCreateUnexistant = true);

        typedef std::set<FileParserResListener *> TListenersList;
        TListenersList listeners;

        typedef std::map<int,FileInfo *> TEditorInfoMap;
        TEditorInfoMap editorsInfoMap;
        typedef std::map<wxString,FileInfo *> TFileInfoMap;
        TFileInfoMap filesInfoMap;
        typedef std::map<FileInfo *, int> TInfoLockMap;
        TInfoLockMap infosLocksMap;

        wxCriticalSection csFileInfo; // CS d'acces a la liste d'infos
        wxCriticalSection csParser; // CS d'acc�s au thread du parser
        wxMutex           mutexThreadStop; // MUTEX d'arret du thread

        ParsingThread * thread;
        long iData;
        FileInfo * updatedInfo;
};

class FileParserResListener
{
    public:
        virtual ~FileParserResListener() {}

        /** signale des modifications sur un fichier */
        virtual void fileInfoUpdated(FileParserRes * parser, FileInfo * file) = 0;
};

#endif // _PARSER_RES_H_
