/* -*-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 OSG_DisplaySettings
#define OSG_DisplaySettings 1

#include <osg/Referenced>

#include <string>
#include <vector>

namespace osg {

// forward declare
class ArgumentParser;
class ApplicationUsage;

/** DisplaySettings class for encapsulating what visuals are required and
  * have been set up, and the status of stereo viewing.*/
class SG_EXPORT DisplaySettings : public osg::Referenced
{

    public:

        /** Maintain a DisplaySettings singleton for objects to querry at runtime.*/
        static DisplaySettings* instance();


        DisplaySettings()
        {
            setDefaults();
            readEnvironmentalVariables();
        }
        
        DisplaySettings(ArgumentParser& arguments)
        {
            setDefaults();
            readEnvironmentalVariables();
            readCommandLine(arguments);
        }

        DisplaySettings(const DisplaySettings& vs);
        

        DisplaySettings& operator = (const DisplaySettings& vs);
 
        
        void merge(const DisplaySettings& vs);

        void setDefaults();
        
        void readEnvironmentalVariables();

        /** read the commandline arguments.*/
        void readCommandLine(ArgumentParser& arguments);
        
        
        enum DisplayType
        {
            MONITOR,
            POWERWALL,
            REALITY_CENTER,
            HEAD_MOUNTED_DISPLAY
        };

        void setDisplayType(DisplayType type) { _displayType = type; }
        
        DisplayType getDisplayType() const { return _displayType; }


        void setStereo(bool on) { _stereo = on; }
        bool getStereo() const { return _stereo; }

        enum StereoMode
        {
            QUAD_BUFFER,
            ANAGLYPHIC,
            HORIZONTAL_SPLIT,
            VERTICAL_SPLIT,
            LEFT_EYE,
            RIGHT_EYE
        };
        
        void setStereoMode(StereoMode mode) { _stereoMode = mode; }
        StereoMode getStereoMode() const { return _stereoMode; }

        void setEyeSeparation(float eyeSeparation) { _eyeSeparation = eyeSeparation; }
        float getEyeSeparation() const { return _eyeSeparation; }

        void setScreenDistance(float distance) { _screenDistance = distance; }
        float getScreenDistance() const { return _screenDistance; }

        enum SplitStereoHorizontalEyeMapping
        {
            LEFT_EYE_LEFT_VIEWPORT,
            LEFT_EYE_RIGHT_VIEWPORT
        };
        
        void setSplitStereoHorizontalEyeMapping(SplitStereoHorizontalEyeMapping m) { _splitStereoHorizontalEyeMapping = m; }
        SplitStereoHorizontalEyeMapping getSplitStereoHorizontalEyeMapping() const { return _splitStereoHorizontalEyeMapping; }

        void setSplitStereoHorizontalSeparation(int s) { _splitStereoHorizontalSeparation = s; }
        int getSplitStereoHorizontalSeparation() const { return _splitStereoHorizontalSeparation; }

        enum SplitStereoVerticalEyeMapping
        {
            LEFT_EYE_TOP_VIEWPORT,
            LEFT_EYE_BOTTOM_VIEWPORT
        };

        void setSplitStereoVerticalEyeMapping(SplitStereoVerticalEyeMapping m) { _splitStereoVerticalEyeMapping = m; }
        SplitStereoVerticalEyeMapping getSplitStereoVerticalEyeMapping() const { return _splitStereoVerticalEyeMapping; }

        void setSplitStereoVerticalSeparation(int s) { _splitStereoVerticalSeparation = s; }
        int getSplitStereoVerticalSeparation() const { return _splitStereoVerticalSeparation; }

        void setSplitStereoAutoAjustAspectRatio(bool flag) { _splitStereoAutoAdjustAspectRatio=flag; }
        bool getSplitStereoAutoAjustAspectRatio() const { return _splitStereoAutoAdjustAspectRatio; }


        void setScreenHeight(float height) { _screenHeight = height; }
        float getScreenHeight() const { return _screenHeight; }


        void setDoubleBuffer(bool flag) { _doubleBuffer = flag; }
        bool getDoubleBuffer() const { return _doubleBuffer; }


        void setRGB(bool flag) { _RGB = flag; }
        bool getRGB() const { return _RGB; }


        void setDepthBuffer(bool flag) { _depthBuffer = flag; }
        bool getDepthBuffer() const { return _depthBuffer; }


        void setMinimumNumAlphaBits(unsigned int bits) { _minimumNumberAlphaBits = bits; }
        unsigned int getMinimumNumAlphaBits() const { return _minimumNumberAlphaBits; }
        bool getAlphaBuffer() const { return _minimumNumberAlphaBits!=0; }


        void setMinimumNumStencilBits(unsigned int bits) { _minimumNumberStencilBits = bits; }
        unsigned int getMinimumNumStencilBits() const { return _minimumNumberStencilBits; }
        bool getStencilBuffer() const { return _minimumNumberStencilBits!=0; }


        void setMaxNumberOfGraphicsContexts(unsigned int num) { _maxNumOfGraphicsContexts = num; }
        unsigned int getMaxNumberOfGraphicsContexts() const { return _maxNumOfGraphicsContexts; }


    protected:
    
        virtual ~DisplaySettings();

        void copy(const DisplaySettings& vs);

        DisplayType                     _displayType;
        bool                            _stereo;
        StereoMode                      _stereoMode;
        float                           _eyeSeparation;
        float                           _screenDistance;
        float                           _screenHeight;

        SplitStereoHorizontalEyeMapping _splitStereoHorizontalEyeMapping;
        int                             _splitStereoHorizontalSeparation;
        SplitStereoVerticalEyeMapping   _splitStereoVerticalEyeMapping;
        int                             _splitStereoVerticalSeparation;
        bool                            _splitStereoAutoAdjustAspectRatio;
    
        bool                            _doubleBuffer;
        bool                            _RGB;
        bool                            _depthBuffer;
        unsigned int                    _minimumNumberAlphaBits;
        unsigned int                    _minimumNumberStencilBits;

        unsigned int                    _maxNumOfGraphicsContexts;

};

}

# endif
