/*==LICENSE==*

CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011  Cyan Worlds, Inc.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

You can contact Cyan Worlds, Inc. by email legal@cyan.com
 or by snail mail at:
      Cyan Worlds, Inc.
      14617 N Newport Hwy
      Mead, WA   99021

*==LICENSE==*/
//////////////////////////////////////////////////////////////////////////////
//                                                                          //
//  plPassAnimDlgProc - Base Animation Dlg Proc for plPassMtlBase           //
//                                                                          //
//////////////////////////////////////////////////////////////////////////////

#include "hsTypes.h"
#include "plPassAnimDlgProc.h"

#include "plPassBaseParamIDs.h"
#include "MaxComponent/plNotetrackAnim.h"
#include "../resource.h"
#include "iparamm2.h"

#include "plAnimStealthNode.h"

#include "MaxComponent/plMaxAnimUtils.h"
#include "MaxComponent/plAnimComponent.h"
#include "MaxExport/plErrorMsg.h"

const char *kPassNameNone = ENTIRE_ANIMATION_NAME;

#include "plAnimStealthNode.h"

using namespace plPassBaseParamIDs;

plPassAnimDlgProc::plPassAnimDlgProc()
{
    fCurrParamMap = nil;
    fInitingNames = false;
}

plPassAnimDlgProc::~plPassAnimDlgProc()
{
    if( fCurrParamMap != nil )
    {
        plPassMtlBase *mtl = (plPassMtlBase *)( fCurrParamMap->GetParamBlock()->GetOwner() );
        mtl->RegisterChangeCallback( this );
    }
}

plPassAnimDlgProc   &plPassAnimDlgProc::Get( void )
{
    static plPassAnimDlgProc    instance;
    return instance;
}

void plPassAnimDlgProc::Update(TimeValue t, Interval& valid, IParamMap2* pmap)
{
/*  plAnimStealthNode *testStealth = (plAnimStealthNode *)pmap->GetParamBlock()->GetINode( (ParamID)kPBAnimTESTING );
    if( testStealth != nil )
    {
        IParamBlock2 *pb = testStealth->GetParamBlockByID( plAnimStealthNode::kBlockPB );
        if( pb && pb->GetMap() && pb->GetMap()->GetUserDlgProc() )
            pb->GetMap()->GetUserDlgProc()->Update( t, valid, pmap );
    }
*/

    HWND hWnd = pmap->GetHWnd();
    IParamBlock2 *pb = pmap->GetParamBlock();
    plAnimComponentProc::SetBoxToAgeGlobal(GetDlgItem(hWnd, IDC_MTL_GLOBAL_NAME), pb->GetStr(ParamID(kPBAnimGlobalName)));  
}

BOOL plPassAnimDlgProc::DlgProc(TimeValue t, IParamMap2 *pMap, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    if( fCurrParamMap != pMap )
    {
        if( fCurrParamMap != nil )
        {
            plPassMtlBase *mtl = (plPassMtlBase *)( fCurrParamMap->GetParamBlock()->GetOwner() );
            mtl->UnregisterChangeCallback( this );
        }

        fCurrParamMap = pMap;

        if( fCurrParamMap != nil )
        {
            plPassMtlBase *mtl = (plPassMtlBase *)( fCurrParamMap->GetParamBlock()->GetOwner() );
            mtl->RegisterChangeCallback( this );
        }
    }

    IParamBlock2 *pb = pMap->GetParamBlock();
    plPassMtlBase *mtl = (plPassMtlBase*)pb->GetOwner();
    HWND gWnd = GetDlgItem(hWnd, IDC_MTL_GLOBAL_NAME);  
    char buff[512];

    switch (msg)
    {
        case WM_DESTROY:
            if( fCurrParamMap != nil )
            {
                plPassMtlBase *mtl = (plPassMtlBase *)( fCurrParamMap->GetParamBlock()->GetOwner() );
                mtl->RegisterChangeCallback( this );
                fCurrParamMap = nil;
            }
            break;

        case WM_INITDIALOG:
            {
                fhWnd = hWnd;
                fCurrStealth = nil;
                IInitControls(mtl, pb);

                plAnimComponentProc::FillAgeGlobalComboBox(gWnd, pb->GetStr(ParamID(kPBAnimGlobalName)));                           
                plAnimComponentProc::SetBoxToAgeGlobal(gWnd, pb->GetStr(ParamID(kPBAnimGlobalName)));   
                IEnableGlobal(hWnd, pb->GetInt( (ParamID)kPBAnimUseGlobal ) );      

                bool stopPoints = false;
                if( DoesHaveStopPoints( pb->GetOwner() ) )
                {
                    stopPoints = true;
                    break;
                }
                
                IEnableEaseStopPoints( pMap, stopPoints );
            }
            return TRUE;

        case WM_COMMAND:
            // Anim name selection changed
            if (LOWORD(wParam) == IDC_NAMES && HIWORD(wParam) == CBN_SELCHANGE)
            {
                IUpdateSegmentSel( pMap );
                return TRUE;
            }
            // Refresh clicked
            else if (LOWORD(wParam) == IDC_REFRESH_ANIMS && HIWORD(wParam) == BN_CLICKED)
            {
                IInitControls(mtl, pb);
                return TRUE;
            }
            else if (HIWORD(wParam) == CBN_SELCHANGE && LOWORD(wParam) == IDC_MTL_GLOBAL_NAME)
            {
                ComboBox_GetLBText(gWnd, ComboBox_GetCurSel(gWnd), buff);
                pb->SetValue(ParamID(kPBAnimGlobalName), 0, _T(buff));
            }           
            else if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_MTL_USE_GLOBAL)
            {
                IEnableGlobal(hWnd, pb->GetInt( (ParamID)kPBAnimUseGlobal ) );
            }

            break;
    }

    return FALSE;
}

void    plPassAnimDlgProc::SegmentListChanged( void )
{
    if( fCurrParamMap != nil )
        ILoadNames( fCurrParamMap->GetParamBlock() );
}

void    plPassAnimDlgProc::IUpdateSegmentSel( IParamMap2 *thisMap, hsBool clear )
{
    plAnimStealthNode *newStealth;
    HWND hAnims = GetDlgItem( fhWnd, IDC_NAMES );
    
    // Get current selection
    if( clear )
        newStealth = nil;
    else
    {
        int sel = SendDlgItemMessage( fhWnd, IDC_NAMES, CB_GETCURSEL, 0, 0 );
        if( sel == CB_ERR )
        {
            // Somehow we don't have a selection...fine, just destroy
            newStealth = nil;
        }
        else
        {
            newStealth = (plAnimStealthNode *)SendDlgItemMessage( fhWnd, IDC_NAMES, CB_GETITEMDATA, sel, 0 );
        }
    }

    // Did we really not change?
    if( newStealth == fCurrStealth )
        return;

    if( fCurrStealth != nil && newStealth != nil )
    {
        fCurrStealth->SwitchDlg( newStealth );
    }
    else
    {
        // Destroy the old
        if( fCurrStealth != nil )
            fCurrStealth->ReleaseDlg();

        // Show the new
        if( newStealth != nil )
            IExposeStealthNode( newStealth, thisMap );
    }

    // And update!
    fCurrStealth = newStealth;
}


void    plPassAnimDlgProc::IExposeStealthNode( HelperObject *node, IParamMap2 *thisMap )
{
    if( node->ClassID() != ANIMSTEALTH_CLASSID )
        return;

    // Get our stealth pointer
    plAnimStealthNode *stealth = (plAnimStealthNode *)node;

    // Create the paramMap-based dialog for us
    IParamBlock2 *pb = thisMap->GetParamBlock();
    plPassMtlBase *mtl = (plPassMtlBase *)pb->GetOwner();

    if( !stealth->CreateAndEmbedDlg( thisMap, mtl->fIMtlParams, GetDlgItem( fhWnd, IDC_PLACEHOLDER ) ) )
    {
    }
}


void plPassAnimDlgProc::SetThing(ReferenceTarget *m)
{
    plPassMtlBase *mtl = (plPassMtlBase*)m;
    IInitControls(mtl, mtl->fAnimPB );
}

void plPassAnimDlgProc::IInitControls(Animatable *anim, IParamBlock2 *pb)
{
    ILoadNames( pb );
    IEnableGlobal( fhWnd, pb->GetInt( ParamID( kPBAnimUseGlobal ) ) );      
}

void plPassAnimDlgProc::ILoadNames(IParamBlock2 *pb )
{
    // The following is to prevent IGetNumStealths() from re-calling us
    if( fInitingNames )
        return;
    fInitingNames = true;

    HWND hAnims = GetDlgItem(fhWnd, IDC_NAMES);
    SendMessage(hAnims, CB_RESETCONTENT, 0, 0);

    plPassMtlBase *mtl = (plPassMtlBase *)pb->GetOwner();

    // Loop through our stealth nodes and add them all to the combo,
    // since that's what we're selecting...erm, yeah
    int i, count = mtl->IGetNumStealths( true );
    for( i = 0; i < count; i++ )
    {
        plAnimStealthNode *stealth = mtl->IGetStealth( i, false );
        if( stealth != nil )
        {
            int idx = SendMessage( hAnims, CB_ADDSTRING, 0, (LPARAM)stealth->GetSegmentName() );
            SendMessage( hAnims, CB_SETITEMDATA, idx, (LPARAM)stealth );
        }
    }

    SendMessage( hAnims, CB_SETCURSEL, 0, 0 );
    IUpdateSegmentSel( pb->GetMap() );

    fInitingNames = false;
}

void plPassAnimDlgProc::IEnableGlobal(HWND hWnd, hsBool enable)
{
    Edit_Enable(GetDlgItem(hWnd, IDC_MTL_GLOBAL_NAME), enable);
    ComboBox_Enable(GetDlgItem(hWnd, IDC_NAMES), !enable);

    HWND stealthWnd = ( fCurrStealth != nil ) ? fCurrStealth->GetWinDlg() : nil;
    if( stealthWnd != nil )
        EnableWindow( stealthWnd, !enable );
}

void    plPassAnimDlgProc::IEnableEaseStopPoints( IParamMap2 *pm, bool enable )
{
    pm->Enable( (ParamID)kPBAnimEaseInMin, enable );
    pm->Enable( (ParamID)kPBAnimEaseInMax, enable );
    pm->Enable( (ParamID)kPBAnimEaseOutMin, enable );
    pm->Enable( (ParamID)kPBAnimEaseOutMax, enable );
}