/**
    Copyright (c) 2010 yakiimo02
    Distributed under the New BSD License.
    See included license.txt or http://www.yakiimo3d.com/NewBSDLicense.txt
**/

#include "DXUT.h"
#include "GUI.h"
#include "TemporalAA.h"

#define IDC_TOGGLEFULLSCREEN    1
#define IDC_TOGGLEREF           3
#define IDC_CHANGEDEVICE        4

// temporal aa
#define IDC_TEMPORAL_AA_MODE_COMBOBOX         20000

GUI g_gui;

void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext );

/**
*/
GUI::GUI() : m_pTxtHelper( NULL ), m_bDisplayGUI( true ), m_pTemporalAAModeComboBox( NULL )
{
}

/**
    @param pd3dDevice    [in]    D3D Device
*/
HRESULT GUI::Create( ID3D11Device* pd3dDevice )
{
    HRESULT hr = S_OK;

    ID3D11DeviceContext* pd3dImmediateContext = DXUTGetD3D11DeviceContext();
    V_RETURN( m_DialogResourceManager.OnD3D11CreateDevice( pd3dDevice, pd3dImmediateContext ) );
    V_RETURN( m_D3DSettingsDlg.OnD3D11CreateDevice( pd3dDevice ) );
    m_pTxtHelper = new CDXUTTextHelper( pd3dDevice, pd3dImmediateContext, &m_DialogResourceManager, 15 );

     return hr;
}

/**
*/
void GUI::RegistGuiItems()
{
    /** General Dialog */

    m_D3DSettingsDlg.Init( &m_DialogResourceManager );
    m_HUD.Init( &m_DialogResourceManager );

    m_HUD.SetCallback( OnGUIEvent ); 
    int nY = 20;
    m_HUD.AddButton( IDC_TOGGLEFULLSCREEN, L"Toggle full screen", 0, nY, 170, 23 );
    m_HUD.AddButton( IDC_TOGGLEREF, L"Toggle REF (F3)", 0, nY += 26, 170, 23, VK_F3 );
    m_HUD.AddButton( IDC_CHANGEDEVICE, L"Change device (F2)", 0, nY += 26, 170, 23, VK_F2 );

    /** Custom Dialog */

    m_SampleUI.Init( &m_DialogResourceManager );
    m_SampleUI.SetCallback( OnGUIEvent ); 

    /** Temporal AA Stuff */
    m_SampleUI.AddComboBox( IDC_TEMPORAL_AA_MODE_COMBOBOX, 0, nY, 150, 24, 'M', false, &m_pTemporalAAModeComboBox );
    m_pTemporalAAModeComboBox->AddItem( L"NONE", IntToPtr(AA_MODE_NONE) );
    m_pTemporalAAModeComboBox->AddItem( L"HARDWARE_MSAA_2X", IntToPtr(AA_MODE_MSAA_2X) );    
    m_pTemporalAAModeComboBox->AddItem( L"HARDWARE_MSAA_4X", IntToPtr(AA_MODE_MSAA_4X) );    
    m_pTemporalAAModeComboBox->AddItem( L"TEMPORAL_2X", IntToPtr(AA_MODE_TEMPORAL_2X) );    
    m_pTemporalAAModeComboBox->SetSelectedByIndex( g_temporalAA.GetMode() );
    m_pTemporalAAModeComboBox->SetTextColor( D3DCOLOR_XRGB( 0, 0, 255 ) );
    //nY += 24;
}

/**
*/
bool GUI::FrameRender( float fElapsedTime )
{
    // If the settings dialog is being shown, then render it instead of rendering the app's scene
    if( m_D3DSettingsDlg.IsActive() )
    {
        m_D3DSettingsDlg.OnRender( fElapsedTime );
        return true;
    }

    if( m_bDisplayGUI ) {
        DXUT_BeginPerfEvent( DXUT_PERFEVENTCOLOR, L"HUD / Stats" );
        m_HUD.OnRender( fElapsedTime );
        m_SampleUI.OnRender( fElapsedTime );
        RenderText();
        DXUT_EndPerfEvent();
    }

    return false;
}

/**
*/
void GUI::RenderText()
{
    m_pTxtHelper->Begin();
    m_pTxtHelper->SetInsertionPos( 2, 0 );
    m_pTxtHelper->SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) );
    m_pTxtHelper->DrawTextLine( DXUTGetFrameStats( true ) );
    m_pTxtHelper->DrawTextLine( DXUTGetDeviceStats() );

    wchar_t strMsg[ 256 ];

    // help
    swprintf_s( strMsg, L"P=Screenshot, H=Hide GUI" );
    m_pTxtHelper->DrawTextLine( strMsg );

    m_pTxtHelper->End();
}

/**
    @param pd3dDevice        [in]    D3D Device
    @param pBackBufferDesc    [in]    Description of backbuffer
*/
HRESULT GUI::ResizedSwapChain( ID3D11Device* pd3dDevice, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc )
{
    HRESULT hr = S_OK;

    V_RETURN( m_DialogResourceManager.OnD3D11ResizedSwapChain( pd3dDevice, pBackBufferSurfaceDesc ) );
    V_RETURN( m_D3DSettingsDlg.OnD3D11ResizedSwapChain( pd3dDevice, pBackBufferSurfaceDesc ) );

    m_HUD.SetLocation( pBackBufferSurfaceDesc->Width - 170, 0 );
    m_HUD.SetSize( 170, 170 );
    m_SampleUI.SetLocation( pBackBufferSurfaceDesc->Width - 170, pBackBufferSurfaceDesc->Height - 350 );
    m_SampleUI.SetSize( 170, 300 );

    return hr;
}

/**
*/
void GUI::Destroy()
{
    m_DialogResourceManager.OnD3D11DestroyDevice();
    m_D3DSettingsDlg.OnD3D11DestroyDevice();
    SAFE_DELETE( m_pTxtHelper );        
}

/**
*/
void GUI::ReleasingSwapChain()
{
    m_DialogResourceManager.OnD3D11ReleasingSwapChain();
}

/**
*/
LRESULT GUI::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing )
{
    // Pass messages to dialog resource manager calls so GUI state is updated correctly
    *pbNoFurtherProcessing = m_DialogResourceManager.MsgProc( hWnd, uMsg, wParam, lParam );
    if( *pbNoFurtherProcessing )
        return 0;

    // Pass messages to settings dialog if its active
    if( m_D3DSettingsDlg.IsActive() )
    {
        m_D3DSettingsDlg.MsgProc( hWnd, uMsg, wParam, lParam );
        return 0;
    }

    // Give the dialogs a chance to handle the message first
    *pbNoFurtherProcessing = m_HUD.MsgProc( hWnd, uMsg, wParam, lParam );
    if( *pbNoFurtherProcessing )
        return 0;
    *pbNoFurtherProcessing = m_SampleUI.MsgProc( hWnd, uMsg, wParam, lParam );
    if( *pbNoFurtherProcessing )
        return 0;

    return 0;
}

/**
    CDXUTDialog callback.
*/
void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext )
{
    CD3DSettingsDlg& settingsDlg = g_gui.GetrSettingsDlg();

    switch( nControlID )
    {
    case IDC_TOGGLEFULLSCREEN:
        DXUTToggleFullScreen(); 
        break;
    
    case IDC_TOGGLEREF:
        DXUTToggleREF(); 
        break;
    
    case IDC_CHANGEDEVICE:
        settingsDlg.SetActive( !settingsDlg.IsActive() ); 
        break;

    // temporal aa stuff
    case IDC_TEMPORAL_AA_MODE_COMBOBOX:
        CDXUTComboBox* pComboBox = ( CDXUTComboBox* )pControl;
        g_temporalAA.SetMode( static_cast< AAMode >( PtrToInt( pComboBox->GetSelectedData() ) ) );
        break;
    }
}
