/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_chart2.hxx"

#include "tp_3D_SceneAppearance.hxx"
#include "tp_3D_SceneAppearance.hrc"
#include "ResId.hxx"
#include "Strings.hrc"
#include "NoWarningThisInCTOR.hxx"
#include "ChartModelHelper.hxx"
#include "ThreeDHelper.hxx"
#include "macros.hxx"
#include <rtl/math.hxx>
#include <com/sun/star/beans/XPropertySet.hpp>

using namespace ::com::sun::star;

namespace
{

struct lcl_ModelProperties
{
    drawing::ShadeMode        m_aShadeMode;
    sal_Int32                 m_nRoundedEdges;
    sal_Int32                 m_nObjectLines;
    ::chart::ThreeDLookScheme m_eScheme;

    lcl_ModelProperties() :
            m_nRoundedEdges(-1),
            m_nObjectLines(-1),
            m_eScheme(::chart::ThreeDLookScheme_Unknown)
    {}
};

lcl_ModelProperties lcl_getPropertiesFromModel( uno::Reference< frame::XModel > & xModel )
{
    lcl_ModelProperties aProps;
    try
    {
        uno::Reference< chart2::XDiagram > xDiagram( ::chart::ChartModelHelper::findDiagram( xModel ) );
        uno::Reference< beans::XPropertySet > xDiaProp( xDiagram, uno::UNO_QUERY_THROW );
        xDiaProp->getPropertyValue( C2U("D3DSceneShadeMode")) >>= aProps.m_aShadeMode;
        ::chart::ThreeDHelper::getRoundedEdgesAndObjectLines( xDiagram, aProps.m_nRoundedEdges, aProps.m_nObjectLines );
        aProps.m_eScheme = ::chart::ThreeDHelper::detectScheme( xDiagram );
    }
    catch( const uno::Exception & ex )
    {
        ASSERT_EXCEPTION( ex );
    }
    return aProps;
}

void lcl_setShadeModeAtModel( uno::Reference< frame::XModel > & xModel, drawing::ShadeMode aShadeMode )
{
    try
    {
        uno::Reference< beans::XPropertySet > xDiaProp(
            ::chart::ChartModelHelper::findDiagram( xModel ), uno::UNO_QUERY_THROW );
        xDiaProp->setPropertyValue( C2U("D3DSceneShadeMode"), uno::makeAny( aShadeMode ));
    }
    catch( const uno::Exception & ex )
    {
        ASSERT_EXCEPTION( ex );
    }
}

} // anonymous namespace

//.............................................................................
namespace chart
{
//.............................................................................

#define POS_3DSCHEME_SIMPLE    0
#define POS_3DSCHEME_REALISTIC 1
#define POS_3DSCHEME_CUSTOM 2

ThreeD_SceneAppearance_TabPage::ThreeD_SceneAppearance_TabPage(
      Window* pWindow
    , const uno::Reference< frame::XModel > & xChartModel
    , ControllerLockHelper & rControllerLockHelper )
                : TabPage 	        ( pWindow, SchResId( TP_3D_SCENEAPPEARANCE ) )
                , m_xChartModel     ( xChartModel )
                , m_aFT_Scheme      ( this, SchResId( FT_SCHEME ) )
                , m_aLB_Scheme      ( this, SchResId( LB_SCHEME ) )
                , m_aFL_Seperator   ( this, SchResId( FL_SEPERATOR ) )
                , m_aCB_Shading	    ( this, SchResId( CB_SHADING ) )
                , m_aCB_ObjectLines ( this, SchResId( CB_OBJECTLINES ) )
                , m_aCB_RoundedEdge ( this, SchResId( CB_ROUNDEDEDGE ) )
                , m_bUpdateOtherControls( true )
                , m_bCommitToModel( true )
                , m_rControllerLockHelper( rControllerLockHelper )
{
	FreeResource();
    m_aLB_Scheme.InsertEntry(String(SchResId(STR_3DSCHEME_SIMPLE)),POS_3DSCHEME_SIMPLE);
    m_aLB_Scheme.InsertEntry(String(SchResId(STR_3DSCHEME_REALISTIC)),POS_3DSCHEME_REALISTIC);
    m_aLB_Scheme.SetDropDownLineCount(2);

    m_aLB_Scheme.SetSelectHdl( LINK( this, ThreeD_SceneAppearance_TabPage, SelectSchemeHdl ) );

    m_aCB_RoundedEdge.SetToggleHdl( LINK( this, ThreeD_SceneAppearance_TabPage, SelectRoundedEdgeOrObjectLines ) );
    m_aCB_Shading.SetToggleHdl( LINK( this, ThreeD_SceneAppearance_TabPage, SelectShading ) );
    m_aCB_ObjectLines.SetToggleHdl( LINK( this, ThreeD_SceneAppearance_TabPage, SelectRoundedEdgeOrObjectLines ) );

    m_aCB_RoundedEdge.EnableTriState( sal_True );
    m_aCB_Shading.EnableTriState( sal_True );
    m_aCB_ObjectLines.EnableTriState( sal_True );

    initControlsFromModel();
}

ThreeD_SceneAppearance_TabPage::~ThreeD_SceneAppearance_TabPage()
{}

void ThreeD_SceneAppearance_TabPage::ActivatePage()
{
    updateScheme();
}

void ThreeD_SceneAppearance_TabPage::commitPendingChanges()
{
}

void ThreeD_SceneAppearance_TabPage::applyRoundedEdgeAndObjectLinesToModel()
{
    if(!m_bCommitToModel)
        return;

    sal_Int32 nObjectLines = -1;

    switch( m_aCB_ObjectLines.GetState())
    {
        case STATE_NOCHECK:
            nObjectLines = 0;
            break;
        case STATE_CHECK:
            nObjectLines = 1;
            break;
        case STATE_DONTKNOW:
            nObjectLines = -1;
            break;
    }

    sal_Int32 nCurrentRoundedEdges = -1;
    switch( m_aCB_RoundedEdge.GetState() )
    {
        case STATE_NOCHECK:
            nCurrentRoundedEdges = 0;
            break;
        case STATE_CHECK:
            nCurrentRoundedEdges = 5;
            break;
        case STATE_DONTKNOW:
            nCurrentRoundedEdges = -1;
            break;
    }

    // /-- locked controllers
    ControllerLockHelperGuard aGuard( m_rControllerLockHelper );
    ThreeDHelper::setRoundedEdgesAndObjectLines(
        ::chart::ChartModelHelper::findDiagram( m_xChartModel ), nCurrentRoundedEdges, nObjectLines );
    // \-- locked controllers
}

void ThreeD_SceneAppearance_TabPage::applyShadeModeToModel()
{
    if(!m_bCommitToModel)
        return;

    drawing::ShadeMode aShadeMode = drawing::ShadeMode_PHONG;

    switch( m_aCB_Shading.GetState())
    {
        case STATE_NOCHECK:
            aShadeMode = drawing::ShadeMode_FLAT;
            break;
        case STATE_CHECK:
            aShadeMode = drawing::ShadeMode_SMOOTH;
            break;
        case STATE_DONTKNOW:
            // nothing
            break;
    }

    lcl_setShadeModeAtModel( m_xChartModel, aShadeMode );
}

void ThreeD_SceneAppearance_TabPage::initControlsFromModel()
{
    m_bCommitToModel = false;
    m_bUpdateOtherControls = false;

    lcl_ModelProperties aProps( lcl_getPropertiesFromModel( m_xChartModel ));

    if(aProps.m_aShadeMode == drawing::ShadeMode_FLAT)
    {
        m_aCB_Shading.EnableTriState( sal_False );
        m_aCB_Shading.Check(sal_False);
    }
    else if(aProps.m_aShadeMode == drawing::ShadeMode_SMOOTH)
    {
        m_aCB_Shading.EnableTriState( sal_False );
        m_aCB_Shading.Check(sal_True);
    }
    else
    {
        m_aCB_Shading.EnableTriState( sal_True );
        m_aCB_Shading.SetState( STATE_DONTKNOW );
    }

    if(aProps.m_nObjectLines == 0)
    {
        m_aCB_ObjectLines.EnableTriState( sal_False );
        m_aCB_ObjectLines.Check(sal_False);
    }
    else if(aProps.m_nObjectLines==1)
    {
        m_aCB_ObjectLines.EnableTriState( sal_False );
        m_aCB_ObjectLines.Check(sal_True);
    }
    else
    {
        m_aCB_ObjectLines.EnableTriState( sal_True );
        m_aCB_ObjectLines.SetState( STATE_DONTKNOW );
    }

    if(aProps.m_nRoundedEdges >= 5)
    {
        m_aCB_RoundedEdge.EnableTriState( sal_False );
        m_aCB_RoundedEdge.Check(sal_True);
    }
    else if(aProps.m_nRoundedEdges<0)
    {
        m_aCB_RoundedEdge.EnableTriState( sal_False );
        m_aCB_RoundedEdge.SetState( STATE_DONTKNOW );
    }
    else
    {
        m_aCB_RoundedEdge.EnableTriState( sal_True );
        m_aCB_RoundedEdge.Check(sal_False);
    }
    m_aCB_RoundedEdge.Enable( !m_aCB_ObjectLines.IsChecked() );

    updateScheme();

    m_bCommitToModel = true;
    m_bUpdateOtherControls = true;
}

void ThreeD_SceneAppearance_TabPage::updateScheme()
{
    lcl_ModelProperties aProps( lcl_getPropertiesFromModel( m_xChartModel ));

    if( m_aLB_Scheme.GetEntryCount() == (POS_3DSCHEME_CUSTOM+1) )
    {
        m_aLB_Scheme.RemoveEntry(POS_3DSCHEME_CUSTOM);
        m_aLB_Scheme.SetDropDownLineCount(2);
    }
    switch( aProps.m_eScheme )
    {
        case ThreeDLookScheme_Simple:
            m_aLB_Scheme.SelectEntryPos( POS_3DSCHEME_SIMPLE );
            break;
        case ThreeDLookScheme_Realistic:
            m_aLB_Scheme.SelectEntryPos( POS_3DSCHEME_REALISTIC );
            break;
        case ThreeDLookScheme_Unknown:
            {
                m_aLB_Scheme.InsertEntry(String(SchResId(STR_3DSCHEME_CUSTOM)),POS_3DSCHEME_CUSTOM);
                m_aLB_Scheme.SelectEntryPos( POS_3DSCHEME_CUSTOM );
                m_aLB_Scheme.SetDropDownLineCount(3);
            }
            break;
    }
}

IMPL_LINK( ThreeD_SceneAppearance_TabPage, SelectSchemeHdl, void*, EMPTYARG )
{
    if( !m_bUpdateOtherControls )
        return 0;

    {
        // /-- locked controllers
        ControllerLockHelperGuard aGuard( m_rControllerLockHelper );

        uno::Reference< chart2::XDiagram > xDiagram( ::chart::ChartModelHelper::findDiagram( m_xChartModel ) );

        if( m_aLB_Scheme.GetSelectEntryPos() == POS_3DSCHEME_REALISTIC )
            ThreeDHelper::setScheme( xDiagram, ThreeDLookScheme_Realistic );
        else if( m_aLB_Scheme.GetSelectEntryPos() == POS_3DSCHEME_SIMPLE )
            ThreeDHelper::setScheme( xDiagram, ThreeDLookScheme_Simple );
        else
        {
            OSL_ENSURE( false, "Invalid Entry selected" );
        }
        // \-- locked controllers
    }

    // update other controls
    initControlsFromModel();
    return 0;
}

IMPL_LINK( ThreeD_SceneAppearance_TabPage, SelectShading, void*, EMPTYARG )
{
    if( !m_bUpdateOtherControls )
        return 0;

    m_aCB_Shading.EnableTriState( sal_False );
    applyShadeModeToModel();
    updateScheme();
    return 0;
}
IMPL_LINK( ThreeD_SceneAppearance_TabPage, SelectRoundedEdgeOrObjectLines, CheckBox*, pCheckBox )
{
    if( !m_bUpdateOtherControls )
        return 0;

    if( pCheckBox == &m_aCB_ObjectLines )
    {
        m_aCB_ObjectLines.EnableTriState( sal_False );
        m_bUpdateOtherControls = false; 
        m_aCB_RoundedEdge.Enable( !m_aCB_ObjectLines.IsChecked() );
        if(!m_aCB_RoundedEdge.IsEnabled())
            m_aCB_RoundedEdge.Check(sal_False);
        m_bUpdateOtherControls = true;
    }
    else
        m_aCB_RoundedEdge.EnableTriState( sal_False ); 
    applyRoundedEdgeAndObjectLinesToModel();
    updateScheme();
    return 0;
}

//.............................................................................
} //namespace chart
//.............................................................................