/**
 * @file llfloatermediasettings.cpp
 * @brief Tabbed dialog for media settings - class implementation
 *
 * $LicenseInfo:firstyear=2002&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * 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 GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#include "llviewerprecompiledheaders.h"

#include "llfloaterreg.h"
#include "llfloatermediasettings.h"
#include "llpanelmediasettingsgeneral.h"
#include "llpanelmediasettingssecurity.h"
#include "llpanelmediasettingspermissions.h"
#include "llviewercontrol.h"
#include "lluictrlfactory.h"
#include "llbutton.h"
#include "llselectmgr.h"
#include "llsdutil.h"

LLFloaterMediaSettings* LLFloaterMediaSettings::sInstance = NULL;

////////////////////////////////////////////////////////////////////////////////
//
LLFloaterMediaSettings::LLFloaterMediaSettings(const LLSD& key)
    : LLFloater(key),
    mTabContainer(NULL),
    mPanelMediaSettingsGeneral(NULL),
    mPanelMediaSettingsSecurity(NULL),
    mPanelMediaSettingsPermissions(NULL),
    mIdenticalHasMediaInfo( true ),
    mMultipleMedia(false),
    mMultipleValidMedia(false)
{
}

////////////////////////////////////////////////////////////////////////////////
//
LLFloaterMediaSettings::~LLFloaterMediaSettings()
{
    if ( mPanelMediaSettingsGeneral )
    {
        delete mPanelMediaSettingsGeneral;
        mPanelMediaSettingsGeneral = NULL;
    }

    if ( mPanelMediaSettingsSecurity )
    {
        delete mPanelMediaSettingsSecurity;
        mPanelMediaSettingsSecurity = NULL;
    }

    if ( mPanelMediaSettingsPermissions )
    {
        delete mPanelMediaSettingsPermissions;
        mPanelMediaSettingsPermissions = NULL;
    }

    sInstance = NULL;
}

////////////////////////////////////////////////////////////////////////////////
//
BOOL LLFloaterMediaSettings::postBuild()
{
    mApplyBtn = getChild<LLButton>("Apply");
    mApplyBtn->setClickedCallback(onBtnApply, this);

    mCancelBtn = getChild<LLButton>("Cancel");
    mCancelBtn->setClickedCallback(onBtnCancel, this);

    mOKBtn = getChild<LLButton>("OK");
    mOKBtn->setClickedCallback(onBtnOK, this);

    mTabContainer = getChild<LLTabContainer>( "tab_container" );

    mPanelMediaSettingsGeneral = new LLPanelMediaSettingsGeneral();
    mTabContainer->addTabPanel(
            LLTabContainer::TabPanelParams().
            panel(mPanelMediaSettingsGeneral));
    mPanelMediaSettingsGeneral->setParent( this );

    // note that "permissions" tab is really "Controls" tab - refs to 'perms' and
    // 'permissions' not changed to 'controls' since we don't want to change
    // shared files in server code and keeping everything the same seemed best.
    mPanelMediaSettingsPermissions = new LLPanelMediaSettingsPermissions();
    mTabContainer->addTabPanel(
            LLTabContainer::TabPanelParams().
            panel(mPanelMediaSettingsPermissions));

    mPanelMediaSettingsSecurity = new LLPanelMediaSettingsSecurity();
    mTabContainer->addTabPanel(
            LLTabContainer::TabPanelParams().
            panel(mPanelMediaSettingsSecurity));
    mPanelMediaSettingsSecurity->setParent( this );

    // restore the last tab viewed from persistance variable storage
    if (!mTabContainer->selectTab(gSavedSettings.getS32("LastMediaSettingsTab")))
    {
        mTabContainer->selectFirstTab();
    };

    sInstance = this;

    return TRUE;
}

//static
LLFloaterMediaSettings* LLFloaterMediaSettings::getInstance()
{
    if ( !sInstance )
    {
        sInstance = (LLFloaterReg::getTypedInstance<LLFloaterMediaSettings>("media_settings"));
    }

    return sInstance;
}

//static
void LLFloaterMediaSettings::apply()
{
    if (sInstance->haveValuesChanged())
    {
        LLSD settings;
        sInstance->mPanelMediaSettingsGeneral->preApply();
        sInstance->mPanelMediaSettingsGeneral->getValues( settings, false );
        sInstance->mPanelMediaSettingsSecurity->preApply();
        sInstance->mPanelMediaSettingsSecurity->getValues( settings, false );
        sInstance->mPanelMediaSettingsPermissions->preApply();
        sInstance->mPanelMediaSettingsPermissions->getValues( settings, false );

        LLSelectMgr::getInstance()->selectionSetMedia( LLTextureEntry::MF_HAS_MEDIA, settings );

        sInstance->mPanelMediaSettingsGeneral->postApply();
        sInstance->mPanelMediaSettingsSecurity->postApply();
        sInstance->mPanelMediaSettingsPermissions->postApply();
    }
}

////////////////////////////////////////////////////////////////////////////////
void LLFloaterMediaSettings::onOpen(const LLSD& key)
{
    if (mPanelMediaSettingsGeneral)
    {
        // media is expensive, so only load it when nessesary.
        // If we need to preload it, set volume to 0 and any pause
        // if applicable, then unpause here
        mPanelMediaSettingsGeneral->updateMediaPreview();
    }
}

////////////////////////////////////////////////////////////////////////////////
void LLFloaterMediaSettings::onClose(bool app_quitting)
{
    if(mPanelMediaSettingsGeneral)
    {
        mPanelMediaSettingsGeneral->onClose(app_quitting);
    }
    LLFloaterReg::hideInstance("whitelist_entry");
}

////////////////////////////////////////////////////////////////////////////////
//static
void LLFloaterMediaSettings::initValues( const LLSD& media_settings, bool editable )
{
    if (sInstance->hasFocus()) return;

    // Clear values
    sInstance->mPanelMediaSettingsGeneral->clearValues(sInstance->mPanelMediaSettingsGeneral, editable, false /*don't update preview*/);
    sInstance->mPanelMediaSettingsSecurity->clearValues(sInstance->mPanelMediaSettingsSecurity, editable);
    sInstance->mPanelMediaSettingsPermissions->clearValues(sInstance->mPanelMediaSettingsPermissions,  editable);

    // update all panels with values from simulator
    sInstance->mPanelMediaSettingsGeneral->
        initValues( sInstance->mPanelMediaSettingsGeneral, media_settings, editable );

    sInstance->mPanelMediaSettingsSecurity->
        initValues( sInstance->mPanelMediaSettingsSecurity, media_settings, editable );

    sInstance->mPanelMediaSettingsPermissions->
        initValues( sInstance->mPanelMediaSettingsPermissions, media_settings, editable );

    // Squirrel away initial values
    sInstance->mInitialValues.clear();
    sInstance->mPanelMediaSettingsGeneral->getValues( sInstance->mInitialValues );
    sInstance->mPanelMediaSettingsSecurity->getValues( sInstance->mInitialValues );
    sInstance->mPanelMediaSettingsPermissions->getValues( sInstance->mInitialValues );

    sInstance->mApplyBtn->setEnabled(editable);
    sInstance->mOKBtn->setEnabled(editable);
}

////////////////////////////////////////////////////////////////////////////////
//
void LLFloaterMediaSettings::commitFields()
{
    if (hasFocus())
    {
        LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
        if (cur_focus && cur_focus->acceptsTextInput())
        {
            cur_focus->onCommit();
        };
    };
}

////////////////////////////////////////////////////////////////////////////////
//static
void LLFloaterMediaSettings::clearValues( bool editable)
{
    if (sInstance)
    {
        // clean up all panels before updating
        sInstance->mPanelMediaSettingsGeneral    ->clearValues(sInstance->mPanelMediaSettingsGeneral,  editable);
        sInstance->mPanelMediaSettingsSecurity   ->clearValues(sInstance->mPanelMediaSettingsSecurity,  editable);
        sInstance->mPanelMediaSettingsPermissions->clearValues(sInstance->mPanelMediaSettingsPermissions,  editable);
    }
}

////////////////////////////////////////////////////////////////////////////////
// static
void LLFloaterMediaSettings::onBtnOK( void* userdata )
{
    sInstance->commitFields();

    sInstance->apply();

    sInstance->closeFloater();
}

////////////////////////////////////////////////////////////////////////////////
// static
void LLFloaterMediaSettings::onBtnApply( void* userdata )
{
    sInstance->commitFields();

    sInstance->apply();

    sInstance->mInitialValues.clear();
    sInstance->mPanelMediaSettingsGeneral->getValues( sInstance->mInitialValues );
    sInstance->mPanelMediaSettingsSecurity->getValues( sInstance->mInitialValues );
    sInstance->mPanelMediaSettingsPermissions->getValues( sInstance->mInitialValues );

}

////////////////////////////////////////////////////////////////////////////////
// static
void LLFloaterMediaSettings::onBtnCancel( void* userdata )
{
    sInstance->closeFloater();
}

////////////////////////////////////////////////////////////////////////////////
// static
void LLFloaterMediaSettings::onTabChanged(void* user_data, bool from_click)
{
    LLTabContainer* self = (LLTabContainer*)user_data;
    gSavedSettings.setS32("LastMediaSettingsTab", self->getCurrentPanelIndex());
}
////////////////////////////////////////////////////////////////////////////////
//
const std::string LLFloaterMediaSettings::getHomeUrl()
{
    if ( mPanelMediaSettingsGeneral )
        return mPanelMediaSettingsGeneral->getHomeUrl();
    else
        return std::string( "" );
}

////////////////////////////////////////////////////////////////////////////////
// virtual
void LLFloaterMediaSettings::draw()
{
    if (NULL != mApplyBtn)
    {
        // Set the enabled state of the "Apply" button if values changed
        mApplyBtn->setEnabled( haveValuesChanged() );
    }

    LLFloater::draw();
}


//private
bool LLFloaterMediaSettings::haveValuesChanged() const
{
    bool values_changed = false;
    // *NOTE: The code below is very inefficient.  Better to do this
    // only when data change.
    // Every frame, check to see what the values are.  If they are not
    // the same as the initial media data, enable the OK/Apply buttons
    LLSD settings;
    sInstance->mPanelMediaSettingsGeneral->getValues( settings );
    sInstance->mPanelMediaSettingsSecurity->getValues( settings );
    sInstance->mPanelMediaSettingsPermissions->getValues( settings );
    LLSD::map_const_iterator iter = settings.beginMap();
    LLSD::map_const_iterator end = settings.endMap();
    for ( ; iter != end; ++iter )
    {
        const std::string &current_key = iter->first;
        const LLSD &current_value = iter->second;
        if ( ! llsd_equals(current_value, mInitialValues[current_key]))
        {
            values_changed = true;
            break;
        }
    }
    return values_changed;
}

bool LLFloaterMediaSettings::instanceExists()
{
    return LLFloaterReg::findTypedInstance<LLFloaterMediaSettings>("media_settings");
}