/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield 
 *
 * This library is open source and may be redistributed and/or modified under  
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or 
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 * 
 * This library 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 
 * OpenSceneGraph Public License for more details.
*/

#ifndef OSGDB_READERWRITER
#define OSGDB_READERWRITER 1

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

#include <osgDB/Export>


#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()); }
                
                bool validObject() { return _object.valid(); }
                bool validImage() { return getImage()!=0; }
                bool validNode() { return getNode()!=0; }

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

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

                ReadStatus status() const { return _status; }
                bool success() const { return _status==FILE_LOADED; }
                bool error() const { return _status==ERROR_IN_READING_FILE; }
                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; }

                WriteStatus status() const { return _status; }
                bool success() const { return _status==FILE_SAVED; }
                bool error() const { return _status==ERROR_IN_WRITING_FILE; }
                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); }

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

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


};

}

#endif // OSG_READERWRITER
