/*
 * Q&D Uninstaller (main.c)
 *
 * Copyright 2000 Andreas Mohr <andi@lisas.de>
 * Copyright 2004 Hannu Valtonen <Hannu.Valtonen@hut.fi>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * ToDo:
 * - add search box for locating entries quickly
 */


#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <windows.h>
#include "main.h"
#include "regstr.h"
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(uninstaller);

/* Work around a Wine bug which defines handles as UINT rather than LPVOID */
#ifdef WINE_STRICT
#define NULL_HANDLE NULL
#else
#define NULL_HANDLE 0
#endif

/* use multi-select listbox */
#undef USE_MULTIPLESEL

/* Delete uninstall registry key after execution.
 * This is probably a bad idea, because it's the
 * uninstall program that is supposed to do that.
 */
#undef DEL_REG_KEY

char appname[18];

static char about_string[] =
    "Wine Application Uninstaller (C) 2004 by Andreas Mohr <andi@lisas.de> and Hannu Valtonen <Hannu.Valtonen@hut.fi>";
static char program_description[] =
	"Please select the application you wish to uninstall:";

typedef struct {
    char *key;
    WCHAR *descr;
    char *command;
    int active;
} uninst_entry;

uninst_entry *entries = NULL;

unsigned int numentries = 0;
int list_need_update = 1;
int oldsel = -1;

struct {
    DWORD style;
    LPCSTR text;
    HWND hwnd;
} button[] =
{
    { BS_PUSHBUTTON, "Add/Remove", 0 },
    { BS_PUSHBUTTON, "About", 0 },
    { BS_PUSHBUTTON, "Exit", 0 }
};

#define NUM (sizeof(button)/sizeof(button[0]))

int FetchUninstallInformation(void);
void UninstallProgram(void);

void ListUninstallPrograms(void)
{
    unsigned int i;
    int len;
    char *descr;

    if (! FetchUninstallInformation())
        return;

    for (i=0; i < numentries; i++)
    {
        len = WideCharToMultiByte(CP_UNIXCP, 0, entries[i].descr, -1, NULL, 0, NULL, NULL); 
        descr = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
        WideCharToMultiByte(CP_UNIXCP, 0, entries[i].descr, -1, descr, len, NULL, NULL); 
        printf("%s|||%s\n", entries[i].key, descr);
        HeapFree(GetProcessHeap(), 0, descr);
    }
}


void RemoveSpecificProgram(char *name)
{
    unsigned int i;

    if (! FetchUninstallInformation())
        return;

    for (i=0; i < numentries; i++)
    {
        if (strcmp(entries[i].key, name) == 0)
        {
            entries[i].active++;
            break;
        }
    }

    if (i < numentries)
        UninstallProgram();
    else
    {
        fprintf(stderr, "Error: could not match application [%s]\n", name);
    }
}

int main( int argc, char *argv[])
{
    MSG msg;
    WNDCLASS wc;
    HWND hWnd;
    LPSTR token = NULL;
    int i = 1;
    HINSTANCE hInst = NULL;

    while( i<argc )
    {
        token = argv[i++];

        /* Handle requests just to list the applications */
        if( !lstrcmpA( token, "--list" ) )
        {
            ListUninstallPrograms();
            return 0;
        }
        else if( !lstrcmpA( token, "--remove" ) )
        {
            if( i >= argc )
            {
                WINE_ERR( "The remove option requires a parameter.\n");
                return 1;
            }

            RemoveSpecificProgram( argv[i++] );
            return 0;
        }
        else 
        {
            WINE_ERR( "unknown option %s\n",token);
            return 1;
        }
    }

    LoadString( hInst, IDS_APPNAME, appname, sizeof(appname));

    wc.style = 0;
    wc.lpfnWndProc = MainProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInst;
    wc.hIcon = LoadIcon( hInst, appname );
    wc.hCursor = LoadCursor( NULL_HANDLE, IDI_APPLICATION );
    wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = appname;

    if (!RegisterClass(&wc)) exit(1);
    hWnd = CreateWindow( appname, "Wine Application Uninstaller",
        WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        NULL_HANDLE, NULL_HANDLE, hInst, NULL );

    if (!hWnd) exit(1);

    ShowWindow( hWnd, SW_SHOW );
    UpdateWindow( hWnd );

    while( GetMessage(&msg, NULL_HANDLE, 0, 0) ) {
	TranslateMessage( &msg );
        DispatchMessage( &msg );
    }
    return msg.wParam;
}

int cmp_by_name(const void *a, const void *b)
{
    return lstrcmpiW(((uninst_entry *)a)->descr, ((uninst_entry *)b)->descr);
}

int FetchUninstallInformation(void)
{
    HKEY hkeyUninst, hkeyApp;
    int i;
    DWORD sizeOfSubKeyName, displen, uninstlen;
    char subKeyName[256];
    char key_app[1024];
    char *p;

    numentries = 0;
    oldsel = -1;
    if ( RegOpenKeyExA(HKEY_LOCAL_MACHINE, REGSTR_PATH_UNINSTALL,
			    0, KEY_READ, &hkeyUninst) != ERROR_SUCCESS )
    {
	MessageBox(0, "Uninstall registry key not available (yet), nothing to do !", appname, MB_OK);
	return 0;
    }

    if (!entries)
	entries = HeapAlloc(GetProcessHeap(), 0, sizeof(uninst_entry));

    strcpy(key_app, REGSTR_PATH_UNINSTALL);
    strcat(key_app, "\\");
    p = key_app+strlen(REGSTR_PATH_UNINSTALL)+1;

    sizeOfSubKeyName = 255;
    for ( i=0;
	  RegEnumKeyExA( hkeyUninst, i, subKeyName, &sizeOfSubKeyName,
		  	 NULL, NULL, NULL, NULL ) != ERROR_NO_MORE_ITEMS;
	  ++i )
    {
	static const WCHAR DisplayNameW[] = {'D','i','s','p','l','a','y','N','a','m','e',0};

	strcpy(p, subKeyName);
	RegOpenKeyExA(HKEY_LOCAL_MACHINE, key_app, 0, KEY_READ, &hkeyApp);

	if ( (RegQueryValueExW(hkeyApp, DisplayNameW,
		0, 0, NULL, &displen) == ERROR_SUCCESS)
	&&   (RegQueryValueExA(hkeyApp, REGSTR_VAL_UNINSTALLER_COMMANDLINE,
		0, 0, NULL, &uninstlen) == ERROR_SUCCESS) )
	{
	    numentries++;
	    entries = HeapReAlloc(GetProcessHeap(), 0, entries, numentries*sizeof(uninst_entry));
	    entries[numentries-1].key =
		    HeapAlloc(GetProcessHeap(), 0, strlen(subKeyName)+1);
	    strcpy(entries[numentries-1].key, subKeyName);
	    entries[numentries-1].descr =
		    HeapAlloc(GetProcessHeap(), 0, displen);
	    RegQueryValueExW(hkeyApp, DisplayNameW, 0, 0,
			    (LPBYTE)entries[numentries-1].descr, &displen);
	    entries[numentries-1].command =
		    HeapAlloc(GetProcessHeap(), 0, uninstlen);
	    entries[numentries-1].active = 0;
	    RegQueryValueExA(hkeyApp, REGSTR_VAL_UNINSTALLER_COMMANDLINE, 0, 0,
			    entries[numentries-1].command, &uninstlen);
	    WINE_TRACE("allocated entry #%d: %s (%s), %s\n",
		numentries, entries[numentries-1].key,
		wine_dbgstr_w(entries[numentries-1].descr),
		entries[numentries-1].command);
	}
	RegCloseKey(hkeyApp);

	sizeOfSubKeyName = 255;
    }
    qsort(entries, numentries, sizeof(uninst_entry), cmp_by_name);
    RegCloseKey(hkeyUninst);
    return 1;
}

void UninstallProgram(void)
{
    unsigned int i;
    char errormsg[1024];
    BOOL res;
    STARTUPINFO si;
    PROCESS_INFORMATION info;
    DWORD exit_code;
#ifdef DEL_REG_KEY
    HKEY hkey;
#endif

    for (i=0; i < numentries; i++)
    {
	if (!(entries[i].active)) /* don't uninstall this one */
	    continue;
	WINE_TRACE("uninstalling %s\n", wine_dbgstr_w(entries[i].descr));
	memset(&si, 0, sizeof(STARTUPINFO));
	si.cb = sizeof(STARTUPINFO);
	si.wShowWindow = SW_NORMAL;
	res = CreateProcess(NULL, entries[i].command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &info);
	if (res == TRUE)
	{   /* wait for the process to exit */
	    WaitForSingleObject(info.hProcess, INFINITE);
	    res = GetExitCodeProcess(info.hProcess, &exit_code);
	    WINE_TRACE("%d: %08lx\n", res, exit_code);
#ifdef DEL_REG_KEY
	    /* delete the application's uninstall entry */
	    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_UNINSTALL,
		0, KEY_READ, &hkey) == ERROR_SUCCESS)
	    {
		RegDeleteKey(hkey, entries[i].key);
		RegCloseKey(hkey);
	    }
#endif
	}
	else
	{
	    sprintf(errormsg, "Execution of uninstall command '%s' failed, perhaps due to missing executable.", entries[i].command);
	    MessageBox(0, errormsg, appname, MB_OK);
	}
    }
    WINE_TRACE("finished uninstall phase.\n");
    list_need_update = 1;
}

LRESULT WINAPI MainProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    HFONT static_font, listbox_font;
    HDC hdc;
    PAINTSTRUCT ps;
    TEXTMETRIC tm;
    unsigned int i;
    int cxChar, cyChar, y, bx, maxx, maxy, wx, wy;
    static HWND hwndList = 0, static_text = 0;
    DWORD style;
    RECT rect;

    switch( msg ) {
    case WM_CREATE:
	{
	hdc = GetDC(hWnd);
	GetTextMetrics(hdc, &tm);
	static_font = CreateFont(tm.tmHeight + tm.tmExternalLeading, 0, 0, 0, 600, FALSE, 0, 0, 0, 0, 0, 0, 0, "Times New Roman");
	listbox_font = CreateFont(tm.tmHeight + tm.tmExternalLeading, 0, 0, 0, 0, TRUE, 0, 0, 0, 0, 0, 0, 0, "Times New Roman");
	cxChar = tm.tmAveCharWidth;
	cyChar = tm.tmHeight + tm.tmExternalLeading;
	ReleaseDC(hWnd, hdc);
	/* FIXME: implement sorting and use LBS_SORT here ! */
	style = (WS_CHILD|WS_VISIBLE|LBS_STANDARD) & ~LBS_SORT;
#ifdef USE_MULTIPLESEL
	style |= LBS_MULTIPLESEL;
#endif
	bx = maxx = cxChar * 3;
	y = maxy = cyChar * 1;
	static_text = CreateWindow("static", program_description,
		WS_CHILD|WS_VISIBLE|SS_LEFT,
		maxx, maxy,
		cxChar * sizeof(program_description), cyChar * 1,
		hWnd, (HMENU)1,
		((LPCREATESTRUCT)lParam)->hInstance, NULL);
	SendMessage(static_text, WM_SETFONT, (WPARAM)static_font, MAKELPARAM(FALSE, 0));
	maxy += cyChar * 2; /*static text + distance */
	hwndList = CreateWindow("listbox", NULL,
		style,
		maxx, maxy,
		cxChar * 50 + GetSystemMetrics(SM_CXVSCROLL), cyChar * 10,
		hWnd, (HMENU) 1,
		(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL);
	SendMessage(hwndList, WM_SETFONT, (WPARAM)listbox_font, MAKELPARAM(FALSE, 0));
	GetWindowRect(hwndList, &rect);
	maxx += (rect.right - rect.left)*1.1;	
	maxy += (rect.bottom - rect.top)*1.1;
	wx = 20*cxChar;
	wy = 7*cyChar/4;
	y = cyChar * 3;
	for (i=0; i < NUM; i++)
	{
	    button[i].hwnd = CreateWindow("button", button[i].text,
		WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
		maxx, y,
		wx, wy,
		hWnd, (HMENU)i,
		((LPCREATESTRUCT)lParam)->hInstance, NULL);
	    if (!button[i].hwnd)
		    PostQuitMessage(0);
	    y += 2*cyChar;
	}
	maxx += wx + cxChar * 4;
	maxy += cyChar * 2; /* window border */
	SetWindowPos(	hWnd, 0,
			0, 0, maxx, maxy,
			SWP_NOMOVE);
        return 0;
	}

    case WM_PAINT:
      {
        hdc = BeginPaint( hWnd, &ps );
	if (list_need_update)
	{
	    int prevsel;
	    prevsel = SendMessage(hwndList, LB_GETCURSEL, 0, 0);
	    if (!(FetchUninstallInformation()))
	    {
	        PostQuitMessage(0);
	        return 0;
	    }
	    SendMessage(hwndList, LB_RESETCONTENT, 0, 0);
	    SendMessage(hwndList, WM_SETREDRAW, FALSE, 0);
	    for (i=0; i < numentries; i++)
	    {
	        WINE_TRACE("adding %s\n", wine_dbgstr_w(entries[i].descr));
	        SendMessageW(hwndList, LB_ADDSTRING, 0, (LPARAM)entries[i].descr);
	    }
	    WINE_TRACE("setting prevsel %d\n", prevsel);
	    if (prevsel != -1)
	        SendMessage(hwndList, LB_SETCURSEL, prevsel, 0 );
	    SendMessage(hwndList, WM_SETREDRAW, TRUE, 0);
	    list_need_update = 0;
	}
        EndPaint( hWnd, &ps );
        return 0;
      }

    case WM_DESTROY:
        PostQuitMessage( 0 );
        return 0;

    case WM_COMMAND:
	if ((HWND)lParam == hwndList)
	{
	    if (HIWORD(wParam) == LBN_SELCHANGE)
	    {
		int sel = SendMessage(hwndList, LB_GETCURSEL, 0, 0);

#ifndef USE_MULTIPLESEL
		if (oldsel != -1)
		{
		    entries[oldsel].active ^= 1; /* toggle */
		    WINE_TRACE("toggling %d old %s\n", entries[oldsel].active,
				wine_dbgstr_w(entries[oldsel].descr));
		}
#endif
		entries[sel].active ^= 1; /* toggle */
		WINE_TRACE("toggling %d %s\n", entries[sel].active,
			    wine_dbgstr_w(entries[oldsel].descr));
		oldsel = sel;
	    }
	}
	else
	if ((HWND)lParam == button[0].hwnd) /* Uninstall button */
        {
	    UninstallProgram();

	    InvalidateRect(hWnd, NULL, TRUE);
	    UpdateWindow(hWnd);

        }
	else
	if ((HWND)lParam == button[1].hwnd) /* About button */
	    MessageBox(0, about_string, "About Wine Application Uninstaller", MB_OK);
	else
	if ((HWND)lParam == button[2].hwnd) /* Exit button */
	    PostQuitMessage(0);
	return 0;
    }

    return( DefWindowProc( hWnd, msg, wParam, lParam ));
}
