/*****************************************************************************
 * $LastChangedDate: 2010-03-15 11:33:16 -0400 (Mon, 15 Mar 2010) $
 * @file
 * @author  Jim E. Brooks  http://www.palomino3d.org
 * @brief   Weather (Singleton).
 *//*
 * LEGAL:   COPYRIGHT (C) 2009 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
 *****************************************************************************/

#define SKY_WEATHER_CC 1
#include "base/module.hh"
#include "base/random.hh"
using namespace base;
#include "sky/module.hh"
#include "sky/conf.hh"
#include "sky/weather.hh"

namespace sky {

INTERN const RGBA RAIN_COLOR( 0.5f, 0.5f, 0.7f, 0.5f );
INTERN const RGBA SNOW_COLOR( 1.0f, 1.0f, 1.0f, 0.5f );
INTERN const fp   RAIN_INTENSITY = 0.8f;
INTERN const fp   SNOW_INTENSITY = 0.6f;

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////  Weather  /////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

Weather* Weather::msInstance;

/*****************************************************************************
 * ctor/dtor.
 *****************************************************************************/
Weather::Weather( void )
:   mEnabled(true),
    mWeather(eWeather_DEFAULT),
    mPrecipitationEffect(new osgParticle::PrecipitationEffect),
    mGroupNode(new GroupNode),     // -- ORDER-DEPENDENT --
    mGraph(new Graph(mGroupNode))  // -- ORDER-DEPENDENT --
{
    // Arrange nodes.
    mGroupNode->addChild( mPrecipitationEffect.get() );

    // Set weather conditions.
    SetWeather( mWeather );

    // Let Sky attach Weather to SceneGraph.
}


Weather::~Weather()
{
    // NOP
}

/*****************************************************************************
 * Enable/disable weather.
 *****************************************************************************/
void
Weather::Enable( const bool enable )
{
CHECK_TYPESIG(mGraph,TYPESIG_GRAPH);

    if ( enable and (not mEnabled) )  // going to be enabled
    {
        mGraph->Enable( true );
    }
    else if ( (not enable) and mEnabled )  // going to be disabled
    {
        // Disable osg::PrecipitationEffect by disabling Graph.
        mGraph->Enable( false );

        // Switch to clear weather (not DEFAULT which is random weather).
        SetWeather( eWeather_CLEAR );
    }

    mEnabled = enable;
}

/*****************************************************************************
 * Set weather conditions (rain, snow, etc).
 *****************************************************************************/
void
Weather::SetWeather( const eWeather weather )
{
CHECK_TYPESIG(mGraph,TYPESIG_GRAPH);

    // NOP if disabled.
    if ( mEnabled )
    {
        mWeather = weather;

        // Random weather?
        if ( weather == eWeather_RANDOM )
        {
            if ( Random::random_ui( 100 ) <= SKY_CONF.mWeatherRainChance )
                mWeather = eWeather_RAIN;
            else if ( Random::random_ui( 100 ) <= SKY_CONF.mWeatherSnowChance )
                mWeather = eWeather_SNOW;
            else
                mWeather = eWeather_CLEAR;
        }

        // Apply change to weather.
        switch ( mWeather )  // mWeather rather than weather
        {
            case Weather::eWeather_RAIN:
            {
                mGraph->Enable( true );
                mPrecipitationEffect->rain( RAIN_INTENSITY );
                mPrecipitationEffect->setParticleColor( RAIN_COLOR );
            }
            break;

            case Weather::eWeather_SNOW:
            {
                mGraph->Enable( true );
                mPrecipitationEffect->snow( SNOW_INTENSITY );
                mPrecipitationEffect->setParticleColor( SNOW_COLOR );
            }
            break;

            case Weather::eWeather_CLEAR: default:
            {
                // Disable osg::PrecipitationEffect by disabling Graph.
                mGraph->Enable( false );
            }
            break;
        }
    }
}

/*****************************************************************************
 * Get weather conditions (rain, snow, etc).
 *****************************************************************************/
Weather::eWeather
Weather::GetWeather( void ) const
{
    return mWeather;
}

} // namespace sky
