/***************************************************************************
 *   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_FILE_INFO_H_
#define _PARSER_FILE_INFO_H_

#include <wx/string.h>
#include <wx/thread.h>
#include <wx/event.h>
#include <wx/stream.h>
#include "lib/lib_string.h"
#include "lib/lib_file.h"
#include "lib/commons.h"

#include <iostream>

DECLARE_EVENT_TYPE(EVENT_FILEINFO_GET_DATA, -1);

class FileParser;

/**
 * contexte d'interpr�tation des donn�es de parsing
 */
class FileContext
{
    public:
        FileContext(const wxString & _sExecutionPath) : sExecutionPath(_sExecutionPath) {}

        /** renvoie le chemin d'ex�cution du rendu */
        const wxString & getExecutionPath() const { return this->sExecutionPath; }

    private:
        wxString sExecutionPath;
};

/**
 * structure g�n�rique de stockage des infos de parsing d'un fichier
 */
class FileInfo : protected wxEvtHandler
{
    public:
        enum FileType { SourcedFile, EditedFile, NewFile, UnexistantFile };

        FileInfo() : type(UnexistantFile), sFileName(wxT("")), iEditorId(0), iLastParseTime(0), dataStream(NULL), bSyncDataBufferFillRequested(false) { this->initEvtHandler(); }
        FileInfo(FileType _t, const wxString & _sFileName) : type(_t), sFileName(libfile::normalize(_sFileName)), iEditorId(0), iLastParseTime(0), dataStream(NULL), bSyncDataBufferFillRequested(false) { this->initEvtHandler(); }
        FileInfo(FileType _t, const int _iEditorId) : type(_t), sFileName(wxT("")), iEditorId(_iEditorId), iLastParseTime(0), dataStream(NULL), bSyncDataBufferFillRequested(false) { this->initEvtHandler(); }
        FileInfo(const FileInfo & info) { (*this) = info; this->initEvtHandler(); }
        FileInfo(const FileInfo * info) { (*this) = (*info); this->initEvtHandler(); }
        virtual ~FileInfo() { this->endDataParsing(); this->terminateEvtHandler(); }

        /** �cris toutes les informations pars�es dans un fichier de cache pour permettre a l'application de lib�rer la m�moire */
        virtual void dumpToCache() = 0;
        /** lis les informations de parsing pr�alablement stock�es dans un fichier de cache */
        virtual bool readFromCache() = 0;
        /** supprime les informations de parsing pr�alablement stock�es dans un fichier de cache */
        virtual void removeCache() = 0;

        /** indique le nom de fichier g�r� par l'objet */
        const wxString & getFileName() const { return this->sFileName; }
        /** d�fini le nom de fichier g�r� par l'objet */
        void setFileName(const wxString & s) { this->sFileName = s; }

        /** indique l'id de l'�diteur associ� � l'objet */
        int getEditorId() const { return this->iEditorId; }

        /** indique le type du fichier */
        const FileType getType() const { return this->type; }
        /** d�fini le type du fichier */
        void setType( FileType t ) { this->type = t; }

        /** indique la date/heure a laquelle le fichier a �t� modifi� pour la derni�re fois */
        long getLastModificationTime();

        /** indique la date/heure a laquelle le fichier a �t� pars� pour la derni�re fois */
        long getLastParseTime() const { return this->iLastParseTime; }
        /** defini la date/heure a laquelle le fichier a �t� pars� pour la derni�re fois */
        void setLastParseTime(long iTime) { this->iLastParseTime = iTime; }

        /** renvoie la liste des fichiers dont d�pend celui-ci (inclusions) sous la forme de chemins relatifs normalis�s */
        virtual const TStringSet & getDependancies() const { return this->dependancies; }

        /** renvoie la liste des fichiers dont d�pend celui-ci (inclusions) sous la forme de chemins absolus
         * normalis�s en fonction d'un contexte d'ex�cution
         * @param context contexte d'ex�cution du rendu
         */
        virtual TStringSet getDependancies(const FileContext & context) const;

        /** cr�e une instance du parser a utiliser pour ce type de fichier. celle-ci devra etre supprim�e par l'appelant */
        virtual FileParser * getParser() const = 0;

        /** v�rifie que le type d�clar� est le bon */
        void checkType();

        /**
         * renvoie la taille du fichier
         */
        uint getFileSize();

        /**
         * pr�pare la lecture des donn�es du fichier
         * @return un flux sur lequel lire les donn�es du fichier. CE FLUX NE DOIT PAS ETRE LIBERE : utiliser endDataParsing !
         */
        std::istream * initDataParsing();
        /**
         * ferme les flux ouverts pour la lecture du fichier
         */
        void endDataParsing();

        /** gestionnaire d'evenement pour r�cup�rer le contenu d'un editeur de mani�re synchrone */
        void onEventGetData( wxCommandEvent &event );

        /** vidange toutes les infos issues du parsing */
        virtual void clear();

        /** ajoute un fichier a la liste des d�pendances */
        virtual void addDependancie(const wxString & sFileName);
        /** enleve un fichier a la liste des d�pendances */
        virtual void removeDependancie(const wxString & sFileName);

        virtual FileInfo & operator=(const FileInfo & info);

        /** copie les infos r�cup�r�es du parsing dans l'instance courante*/
        virtual void copyParsingInfo(const FileInfo * info);

        /** duplique l'instance */
        virtual FileInfo * clone() = 0;
    private:
        void initEvtHandler();
        void terminateEvtHandler();

        FileType type;
        wxString sFileName;
        int iEditorId;
        long iLastParseTime;
        TStringSet dependancies;

        std::istream * dataStream;
        std::string sDataBuffer;
        long iDataBuffer;

        wxCriticalSection csFillingDataBuffer;
        bool bSyncDataBufferFillRequested;
};

class FileParserRes;

class FileInfoLocker
{
    public:
        FileInfoLocker(FileParserRes * res, int iEltId);
        FileInfoLocker(FileParserRes * res, wxString sFileName, bool bAutoCreate = false);
        ~FileInfoLocker();

        FileInfo * getInfo() { return this->info; }
    private:
        FileInfo * info;
        FileParserRes * res;
};

#endif // _PARSER_FILE_INFO_H_
