//C++ header - Open Scene Graph - Copyright (C) 1998-2001 Robert Osfield
//Distributed under the terms of the GNU Library General Public License (LGPL)
//as published by the Free Software Foundation.

#ifndef OSGDB_READERWRITER
#define OSGDB_READERWRITER 1

#include <osg/Referenced>
#include <osg/Image>
#include <osg/Node>

#include <string>

namespace osgDB {


/** pure virtual base class for reading and writing of non native formats. */
class OSGDB_EXPORT ReaderWriter : public osg::Referenced
{
    public:
        virtual ~ReaderWriter() {}
        virtual const char* className() = 0;
        virtual bool acceptsExtension(const std::string& /*extension*/) { return false; }

        class Options : public osg::Referenced
        {
            public:

                Options() {}
                Options(const std::string& str):_str(str) {}
                
                void setOptionString(const std::string& str) { _str = str; }
                const std::string& getOptionString() const { return _str; }

            protected:

                virtual ~Options() {}

                std::string _str;

        };


        class ReadResult
        {
            public:

                enum ReadStatus
                {
                    FILE_NOT_HANDLED,
                    FILE_LOADED,
                    ERROR_IN_READING_FILE
                };

                ReadResult(ReadStatus status=FILE_NOT_HANDLED):_status(status) {}
                ReadResult(const std::string& m):_status(ERROR_IN_READING_FILE),_message(m) {}
                ReadResult(osg::Object* obj):_status(FILE_LOADED),_object(obj) {}
                
                ReadResult(const ReadResult& rr):_status(rr._status),_message(rr._message),_object(rr._object) {}
                ReadResult& operator = (const ReadResult& rr) { if (this==&rr) return *this; _status=rr._status; _message=rr._message;_object=rr._object; return *this; }
                
                osg::Object* getObject() { return _object.get(); }
                osg::Image* getImage() { return dynamic_cast<osg::Image*>(_object.get()); }
                osg::Node* getNode() { return dynamic_cast<osg::Node*>(_object.get()); }
                
                const bool validObject() { return _object.valid(); }
                const bool validImage() { return getImage()!=0; }
                const bool validNode() { return getNode()!=0; }

                osg::Object* takeObject() { osg::Object* obj = _object.get(); if (obj) { obj->ref(); _object=NULL; } return obj; }
                osg::Image* takeImage() { osg::Image* image=dynamic_cast<osg::Image*>(_object.get()); if (image) { image->ref(); _object==NULL; } return image; }
                osg::Node* takeNode() { osg::Node* node=dynamic_cast<osg::Node*>(_object.get()); if (node) { node->ref(); _object==NULL; } return node; }

                const std::string& message() const { return _message; }

                const ReadStatus status() const { return _status; }
                const bool success() const { return _status==FILE_LOADED; }
                const bool error() const { return _status==ERROR_IN_READING_FILE; }
                const bool notHandled() const { return _status==FILE_NOT_HANDLED; }

            protected:
            
                ReadStatus                  _status;
                std::string                 _message;
                osg::ref_ptr<osg::Object>   _object;
        };

        class WriteResult
        {
            public:

                enum WriteStatus
                {
                    FILE_NOT_HANDLED,
                    FILE_SAVED,
                    ERROR_IN_WRITING_FILE
                };

                WriteResult(WriteStatus status=FILE_NOT_HANDLED):_status(status) {}
                WriteResult(const std::string& m):_status(ERROR_IN_WRITING_FILE),_message(m) {}
                
                WriteResult(const WriteResult& rr):_status(rr._status),_message(rr._message) {}
                WriteResult& operator = (const WriteResult& rr) { if (this==&rr) return *this; _status=rr._status; _message=rr._message; return *this; }
                
                const std::string& message() const { return _message; }

                const WriteStatus status() const { return _status; }
                const bool success() const { return _status==FILE_SAVED; }
                const bool error() const { return _status==ERROR_IN_WRITING_FILE; }
                const bool notHandled() const { return _status==FILE_NOT_HANDLED; }

            protected:
            
                WriteStatus                 _status;
                std::string                 _message;
        };

        virtual ReadResult readObject(const std::string& /*fileName*/,const Options* =NULL) { return ReadResult(ReadResult::FILE_NOT_HANDLED); }
        virtual ReadResult readImage(const std::string& /*fileName*/,const Options* =NULL) { return ReadResult(ReadResult::FILE_NOT_HANDLED); }
        virtual ReadResult readNode(const std::string& /*fileName*/,const Options* =NULL) { return ReadResult(ReadResult::FILE_NOT_HANDLED); }

        virtual WriteResult writeObject(const osg::Object& /*obj*/,const std::string& /*fileName*/,const Options* =NULL) {return WriteResult(WriteResult::FILE_NOT_HANDLED); }
        virtual WriteResult writeImage(const osg::Image& /*image*/,const std::string& /*fileName*/,const Options* =NULL) {return WriteResult(WriteResult::FILE_NOT_HANDLED); }
        virtual WriteResult writeNode(const osg::Node& /*node*/,const std::string& /*fileName*/,const Options* =NULL) { return WriteResult(WriteResult::FILE_NOT_HANDLED); }
};

}

#endif // OSG_READERWRITER
