/**************************************************************
 * 
 * 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.
 * 
 *************************************************************/

// QuickStart.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "resource.h"
#include <systools/win32/uwinapi.h>
#include <stdio.h>

#define MY_TASKBAR_NOTIFICATION         WM_USER+1

#define MAX_LOADSTRING 100

// message used to communicate with soffice
#define TERMINATIONVETO_MESSAGE "SO TerminationVeto"
#define TERMINATE_MESSAGE       "SO Terminate"
#define LISTENER_WINDOWCLASS    "SO Listener Class"
#define KILLTRAY_MESSAGE		"SO KillTray"

static  UINT aTerminationVetoMessage = 0x7FFF;
static  UINT aTerminateMessage = 0x7FFF;
static  HMENU popupMenu = NULL;
static  bool bTerminateVeto = true;

#define UPDATE_TIMER   1

// Global Variables:
HINSTANCE hInst;								// current instance
TCHAR szTitle[MAX_LOADSTRING];					// The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];			// The title bar text

TCHAR szExitString[MAX_LOADSTRING];			    
TCHAR szTooltipString[MAX_LOADSTRING];			

// Foward declarations of functions included in this code module:
ATOM				MyRegisterClass(HINSTANCE hInstance);
BOOL				InitInstance(HINSTANCE, int);
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK	About(HWND, UINT, WPARAM, LPARAM);

bool SofficeRuns()
{
    // check for soffice by searching the communication window
    return ( FindWindowEx( NULL, NULL, LISTENER_WINDOWCLASS, NULL ) == NULL ) ? false : true;
}

bool launchSoffice( )
{
    if ( !SofficeRuns() )
    {
        // UINT ret = WinExec( "h:\\office60.630b\\program\\swriter.exe -bean", SW_SHOW );  
        char filename[_MAX_PATH + 1];

		filename[_MAX_PATH] = 0;
        GetModuleFileName( NULL, filename, _MAX_PATH ); // soffice resides in the same dir
        char *p = strrchr( filename, '\\' );
        if ( !p )
            return false;

        strncpy( p+1, "soffice.exe", _MAX_PATH - (p+1 - filename) );

        char imagename[_MAX_PATH + 1];

		imagename[_MAX_PATH] = 0;
        _snprintf(imagename, _MAX_PATH, "\"%s\" -quickstart", filename );

        UINT ret = WinExec( imagename, SW_SHOW );
        if ( ret < 32 )
            return false;
/*
        // wait until we can communicate
        int retry = 30;
        while (retry-- && !SofficeRuns() )
            Sleep(1000);

        return SofficeRuns();
        */
        return true;
    }
    else
        return true;
}

void NotifyListener( HWND hWnd )
{
    static HICON hIconActive=NULL;
    //static HICON hIconInActive=NULL;

    if( !hIconActive )
    {
        hIconActive = (HICON)LoadImage( GetModuleHandle( NULL ), MAKEINTRESOURCE( ICON_ACTIVE ), 
            IMAGE_ICON, GetSystemMetrics( SM_CXSMICON ), GetSystemMetrics( SM_CYSMICON ),
            LR_DEFAULTCOLOR | LR_SHARED );

/*        hIconInActive = (HICON)LoadImage( GetModuleHandle( NULL ), MAKEINTRESOURCE( ICON_INACTIVE ), 
            IMAGE_ICON, GetSystemMetrics( SM_CXSMICON ), GetSystemMetrics( SM_CYSMICON ),
            LR_DEFAULTCOLOR | LR_SHARED );
            */
    }

    NOTIFYICONDATA nid;
    nid.cbSize = sizeof(NOTIFYICONDATA); 
    nid.hWnd   = hWnd; 
    nid.uID    = IDM_QUICKSTART; 
	nid.szTip[elementsof(nid.szTip) - 1] = 0;
//    nid.hIcon = bTerminateVeto ? hIconActive : hIconInActive;
//    strncpy(nid.szTip, bTerminateVeto ? STRING_QUICKSTARTACTIVE : STRING_QUICKSTARTINACTIVE, elementsof(nid.szTip) - 1 ); 
    nid.hIcon = hIconActive;
    strncpy(nid.szTip, szTooltipString, elementsof(nid.szTip) - 1); 
    nid.uFlags = NIF_TIP|NIF_ICON; 

    // update systray
    Shell_NotifyIcon( NIM_MODIFY, &nid );	
    //CheckMenuItem( popupMenu, IDM_QUICKSTART, bTerminateVeto ? MF_CHECKED : MF_UNCHECKED );

    // notify listener
    SendMessage( HWND_BROADCAST, aTerminationVetoMessage, (WORD) bTerminateVeto, 0L );
}



int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE /*hPrevInstance*/,
                     LPSTR     /*lpCmdLine*/,
                     int       nCmdShow)
{
	// Look for -killtray argument

	for ( int i = 1; i < __argc; i++ )
	{
		if ( 0 == strcmp( __argv[i], "-killtray" ) )
		{
			HWND	hwndTray = FindWindow( LISTENER_WINDOWCLASS, NULL );

			if ( hwndTray )
			{
				UINT	uMsgKillTray = RegisterWindowMessage( KILLTRAY_MESSAGE );
				SendMessage( hwndTray, uMsgKillTray, 0, 0 );
			}

			return 0;
		}
	}

    launchSoffice();
    return 0;

 	// TODO: Place code here.
	MSG msg;
	HACCEL hAccelTable;
    aTerminationVetoMessage = RegisterWindowMessage( TERMINATIONVETO_MESSAGE );
    aTerminateMessage       = RegisterWindowMessage( TERMINATE_MESSAGE );

	// Initialize global strings
	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	LoadString(hInstance, IDC_QUICKSTART, szWindowClass, MAX_LOADSTRING);

	LoadString(hInstance, IDS_EXIT,    szExitString, MAX_LOADSTRING);
	LoadString(hInstance, IDS_TOOLTIP, szTooltipString, MAX_LOADSTRING);

	MyRegisterClass(hInstance);

	// Perform application initialization:
	if (!InitInstance (hInstance, nCmdShow)) 
	{
		return FALSE;
	}

	hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_QUICKSTART);

	// Main message loop:
	while (GetMessage(&msg, NULL, 0, 0)) 
	{
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	return msg.wParam;
}



//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//    This function and its usage is only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX); 

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= (WNDPROC)WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, (LPCTSTR)IDI_QUICKSTART);
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= NULL;
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);

	return RegisterClassEx(&wcex);
}

//
//   FUNCTION: InitInstance(HANDLE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // Store instance handle in our global variable

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return FALSE;
   }

   nCmdShow = SW_HIDE;   // hide main window, we only need the taskbar icon
   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

//
//  FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND	- process the application menu
//  WM_PAINT	- Paint the main window
//  WM_DESTROY	- post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message) 
	{
        case WM_CREATE:
        {
            // make sure soffice runs
            if( !launchSoffice() )
                return -1;

            // create popup menu
            popupMenu = CreatePopupMenu();
            static int count=0;

            // Add my items
            MENUITEMINFO mi;
            mi.cbSize = sizeof(MENUITEMINFO); 
            mi.fMask=MIIM_TYPE|MIIM_STATE|MIIM_ID; 
            mi.fType=MFT_STRING; 
            mi.fState=MFS_ENABLED|MFS_DEFAULT; 
            mi.wID = IDM_QUICKSTART; 
            mi.hSubMenu=NULL; 
            mi.hbmpChecked=NULL; 
            mi.hbmpUnchecked=NULL; 
            mi.dwItemData=NULL; 
            mi.dwTypeData = "QuickStart"; 
            mi.cch = strlen(mi.dwTypeData);
//            InsertMenuItem(popupMenu, count++, TRUE, &mi);

            mi.cbSize = sizeof(MENUITEMINFO); 
            mi.fMask=MIIM_TYPE|MIIM_STATE|MIIM_ID; 
            mi.fType=MFT_STRING; 
            mi.fState=MFS_ENABLED; 
            mi.wID = IDM_ABOUT; 
            mi.hSubMenu=NULL; 
            mi.hbmpChecked=NULL; 
            mi.hbmpUnchecked=NULL; 
            mi.dwItemData=NULL; 
            mi.dwTypeData = "Info..."; 
            mi.cch = strlen(mi.dwTypeData);
//            InsertMenuItem(popupMenu, count++, TRUE, &mi);

            mi.cbSize = sizeof(MENUITEMINFO); 
            mi.fMask=MIIM_TYPE;
            mi.fType=MFT_SEPARATOR; 
            mi.hSubMenu=NULL; 
            mi.hbmpChecked=NULL; 
            mi.hbmpUnchecked=NULL; 
            mi.dwItemData=NULL; 
//            InsertMenuItem(popupMenu, count++, TRUE, &mi);

            mi.cbSize = sizeof(MENUITEMINFO); 
            mi.fMask=MIIM_TYPE|MIIM_STATE|MIIM_ID; 
            mi.fType=MFT_STRING; 
            mi.fState=MFS_ENABLED; 
            mi.wID = IDM_EXIT; 
            mi.hSubMenu=NULL; 
            mi.hbmpChecked=NULL; 
            mi.hbmpUnchecked=NULL; 
            mi.dwItemData=NULL; 
            mi.dwTypeData = szExitString; 
            mi.cch = strlen(mi.dwTypeData);
            InsertMenuItem(popupMenu, count++, TRUE, &mi);

            // add taskbar icon
            NOTIFYICONDATA nid;
            nid.cbSize = sizeof(NOTIFYICONDATA); 
            nid.hWnd   = hWnd; 
            nid.uID    = IDM_QUICKSTART; 
            nid.uFlags = NIF_MESSAGE; 
            nid.uCallbackMessage=MY_TASKBAR_NOTIFICATION; 
            Shell_NotifyIcon(NIM_ADD, &nid);	

            // and update state
            NotifyListener( hWnd );

            // check for soffice
            SetTimer(hWnd, UPDATE_TIMER, 3000, NULL);
        }
        break;
        
        case MY_TASKBAR_NOTIFICATION: // message from taskbar
            switch(lParam)
            {
/*
                case WM_LBUTTONDBLCLK:
                    bTerminateVeto = bTerminateVeto ? false : true;
                    NotifyListener( hWnd );
                    break;
                    */

                case WM_LBUTTONDOWN: 
                case WM_RBUTTONDOWN: 
                {
                    POINT pt;
                    GetCursorPos(&pt);
                    SetForegroundWindow( hWnd );
                    int m = TrackPopupMenuEx(popupMenu, TPM_RETURNCMD|TPM_LEFTALIGN|TPM_RIGHTBUTTON, 
                        pt.x, pt.y, hWnd, NULL);
                    // BUGFIX: See Q135788 (PRB: Menus for Notification Icons Don't Work Correctly)
                    PostMessage(hWnd, NULL, 0, 0);
                    switch(m)
                    {
                    case IDM_QUICKSTART:
                        bTerminateVeto = bTerminateVeto ? false : true;
                        NotifyListener( hWnd );
                        break;
                    case IDM_ABOUT:
                        DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
                        break;
                    case IDM_EXIT:
                        DestroyWindow(hWnd);
                        break;
                    }
                }
                break;
            }
            break;

		case WM_TIMER:
            if( wParam == UPDATE_TIMER )
            {
                // update state
                NotifyListener( hWnd );
            }
            break;

		case WM_DESTROY:
            // try to terminate office
            SendMessage( HWND_BROADCAST, aTerminateMessage, 0, 0L );

            // delete taskbar icon
            NOTIFYICONDATA nid;
            nid.cbSize=sizeof(NOTIFYICONDATA); 
            nid.hWnd = hWnd; 
            nid.uID = IDM_QUICKSTART; 
            Shell_NotifyIcon(NIM_DELETE, &nid);	

			PostQuitMessage(0);
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
   }
   return 0;
}

// Mesage handler for about box.
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM)
{
	switch (message)
	{
		case WM_INITDIALOG:
				return TRUE;

		case WM_COMMAND:
			if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
			{
				EndDialog(hDlg, LOWORD(wParam));
				return TRUE;
			}
			break;
	}
    return FALSE;
}
