//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: 
//
// $NoKeywords: $
//=============================================================================//

#include "stdafx.h"
#include "shell_icon_mgr.h"
#include "tier1/strtools.h"
#include "tier0/dbg.h"
#include "shellapi.h"


#define SHELLICONMGR_CLASSNAME	"VMPI_ShellIconMgr"



CShellIconMgr::CShellIconMgr()
{
	m_hWnd = NULL;
	m_hWndClass = NULL;
	m_uTaskbarRestart = (UINT)-1;
	m_iCurIconResourceID = 0;
	m_pHelper = NULL;
}


CShellIconMgr::~CShellIconMgr()
{
	Term();
}


bool CShellIconMgr::Init( 
	IShellIconMgrHelper *pHelper, 
	const char *pToolTip, 
	int iCallbackMessage, 
	int iIconResourceID )
{
	Term();

	m_pHelper = pHelper;
	m_iCallbackMessage = iCallbackMessage;
	m_pToolTip = pToolTip;
	
	// Create the window class.
	WNDCLASS wndclass;
	memset( &wndclass, 0, sizeof( wndclass ) );
	wndclass.lpfnWndProc = &CShellIconMgr::StaticWindowProc;
	wndclass.hInstance = (HINSTANCE)pHelper->GetHInstance();
	wndclass.hIcon = NULL;
	wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
	wndclass.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH );
	wndclass.lpszMenuName = NULL;
	wndclass.lpszClassName = SHELLICONMGR_CLASSNAME;
	m_hWndClass = RegisterClass( &wndclass );
	if ( !m_hWndClass )
	{
		Assert( false );
		Warning( "RegisterClass failed.\n" );
		Term();
		return false;
	}


	// Create the window.
	m_hWnd = CreateWindow(
		SHELLICONMGR_CLASSNAME,
		SHELLICONMGR_CLASSNAME,
		WS_DISABLED,	// we only want shell notify messages
		0, 0, 0, 0,		// position
		NULL,			// parent
		NULL,			// menu
		pHelper->GetHInstance(),	// hInstance
		this			// lpParam
		);
	if ( !m_hWnd )
	{
		Assert( false );
		Warning( "CreateWindow failed.\n" );
		Term();
		return false;
	}

	m_uTaskbarRestart = RegisterWindowMessage( TEXT( "TaskbarCreated" ) );
	SetWindowLong( m_hWnd, GWL_USERDATA, (LONG)this );
	UpdateWindow( m_hWnd );

	// Don't handle errors here because the taskbar may not be created yet if we are a service.
	m_iCurIconResourceID = iIconResourceID;
	CreateTrayIcon();
	return true;
}


void CShellIconMgr::Term()
{
	if ( m_hWndClass )
	{
		UnregisterClass( SHELLICONMGR_CLASSNAME, m_pHelper->GetHInstance() );
		m_hWndClass = NULL;
	}

	if ( m_hWnd )
	{
		// Remove the shell icon if there is one.
		NOTIFYICONDATA data;
		memset( &data, 0, sizeof( data ) );
		data.cbSize = sizeof( data );
		data.hWnd = m_hWnd;
		Shell_NotifyIcon( NIM_DELETE, &data );
		
		DestroyWindow( m_hWnd );
		m_hWnd = NULL;
	}
}


void CShellIconMgr::ChangeIcon( int iIconResourceID )
{
	NOTIFYICONDATA data;
	
	memset( &data, 0, sizeof( data ) );
	data.cbSize = sizeof( data );
	data.uFlags = NIF_ICON;
	data.hWnd = m_hWnd;
	data.hIcon = LoadIcon( m_pHelper->GetHInstance(), MAKEINTRESOURCE( iIconResourceID ) );
	
	Shell_NotifyIcon( NIM_MODIFY, &data );
	
	m_iCurIconResourceID = iIconResourceID;
}


void CShellIconMgr::CreateTrayIcon()
{
	// Now create the shell icon.
	NOTIFYICONDATA data;
	
	memset( &data, 0, sizeof( data ) );
	data.cbSize = sizeof( data );
	data.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE;
	data.uCallbackMessage = m_iCallbackMessage;
	data.hWnd = m_hWnd;
	data.hIcon = LoadIcon( m_pHelper->GetHInstance(), MAKEINTRESOURCE( m_iCurIconResourceID ) );
	Q_strncpy( data.szTip, m_pToolTip, sizeof( data.szTip ) );

	Shell_NotifyIcon( NIM_ADD, &data );
}


LRESULT CShellIconMgr::WindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
	if ( hWnd != m_hWnd )
	{
		return DefWindowProc( hWnd, uMsg, wParam, lParam );
	}

	if ( uMsg == m_uTaskbarRestart )
	{
		CreateTrayIcon();
		return 0;
	}

	return m_pHelper->WindowProc( hWnd, uMsg, wParam, lParam );
}


LRESULT CShellIconMgr::StaticWindowProc(
	HWND hwnd,      // handle to window
	UINT uMsg,      // message identifier
	WPARAM wParam,  // first message parameter
	LPARAM lParam   // second message parameter
	)
{
	CShellIconMgr *pMgr = (CShellIconMgr*)GetWindowLong( hwnd, GWL_USERDATA );
	if ( pMgr )
	{
		return pMgr->WindowProc( hwnd, uMsg, wParam, lParam );
	}
	else
	{
		return DefWindowProc( hwnd, uMsg, wParam, lParam );
	}
}