/*
 * WineCfg app settings tabsheet
 *
 * Copyright 2004 Robert van Herk
 *                Chris Morgan
 *
 * 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
 *
 */

#define NONAMELESSUNION
#include <windows.h>
#include <commdlg.h>
#include <wine/debug.h>
#include <stdio.h>
#include "winecfg.h"
#include "resource.h"

WINE_DEFAULT_DEBUG_CHANNEL(winecfg);

typedef struct _APPL
{
  BOOL isGlobal;
  char* lpcApplication;
  char* lpcVersionSection;
} APPL, *LPAPPL;

static LPAPPL CreateAppl(BOOL isGlobal, char* application, char* version_section)
{
  LPAPPL out;
  WINE_TRACE("application: '%s', version_section: '%s'\n", application, version_section);
  out = HeapAlloc(GetProcessHeap(),0,sizeof(APPL));
  out->lpcApplication = strdup(application);
  out->lpcVersionSection = strdup(version_section);
  out->isGlobal = isGlobal;
  return out;
}

static VOID FreeAppl(LPAPPL lpAppl)
{
 /* The strings were strdup-ped, so we use "free" */
  if (lpAppl->lpcApplication) free(lpAppl->lpcApplication);
  if (lpAppl->lpcVersionSection) free(lpAppl->lpcVersionSection);
  HeapFree(GetProcessHeap(),0,lpAppl);
}

/* section can be "Version" */
/* key can be "Windows"/"Dos" */
/* value can be appropriate values for the above keys */
typedef struct _APPSETTING
{
  char* section;
  char* lpcKey;
  char* value;
} APPSETTING, *LPAPPSETTING;

static LPAPPSETTING CreateAppSetting(char* lpcKey, char* value)
{
	LPAPPSETTING out = HeapAlloc(GetProcessHeap(),0,sizeof(APPSETTING));
	out->lpcKey = strdup (lpcKey);
	out->value = strdup(value);
	return out;
}

static VOID FreeAppSetting(LPAPPSETTING las)
{
  if (las->lpcKey) free(las->lpcKey);
  if (las->value) free(las->value);
  HeapFree(GetProcessHeap(),0,las);
}

typedef struct _ITEMTAG
{
  LPAPPL lpAppl;
  LPAPPSETTING lpSetting;
} ITEMTAG, *LPITEMTAG;

static LPITEMTAG CreateItemTag()
{
  LPITEMTAG out;
  out = HeapAlloc(GetProcessHeap(),0,sizeof(ITEMTAG));
  out->lpAppl = 0;
  out->lpSetting = 0;
  return out;
}

static VOID FreeItemTag(LPITEMTAG lpit)
{
  /* if child, only free the lpSetting, the lpAppl will be freed when we free the parents item tag */
  if (lpit->lpSetting)
  {
    FreeAppSetting(lpit->lpSetting);
  } else
  {
    if (lpit->lpAppl)
      FreeAppl(lpit->lpAppl);
  }
  HeapFree(GetProcessHeap(), 0, lpit);
}

static VOID LoadAppSettings(LPAPPL appl /*DON'T FREE, treeview will own this*/, HWND hDlg, HWND hwndTV)
{
  HKEY key;
  int i;
  DWORD size;
  DWORD readSize;
  char name [255];
  char read [255];
  char *description;
  LPITEMTAG lpIt;
  TVINSERTSTRUCT tis;	
  HTREEITEM hParent;
  LPAPPSETTING lpas;
	
  WINE_TRACE("opening '%s'\n", appl->lpcVersionSection);
  if (RegOpenKey (configKey, appl->lpcVersionSection, &key) == ERROR_SUCCESS)
  {
     i = 0;
     size = 255;
     readSize = 255;

     lpIt = CreateItemTag();
     lpIt->lpAppl = appl;

     tis.hParent = NULL;
     tis.hInsertAfter = TVI_LAST;
     tis.u.item.mask = TVIF_TEXT | TVIF_PARAM;
     tis.u.item.pszText = appl->lpcApplication;
     tis.u.item.lParam = (LPARAM)lpIt;
     hParent = TreeView_InsertItem(hwndTV,&tis);
     tis.hParent = hParent;

     /* insert version entries */
     if(RegOpenKey (configKey, appl->lpcVersionSection, &key) == ERROR_SUCCESS)
     {
       while (RegEnumValue(key, i, name, &size, NULL, NULL, read, &readSize) == ERROR_SUCCESS)
       {
	 char itemtext[128];

	 WINE_TRACE("Reading value %s, namely %s\n", name, read);
			
	 lpIt = CreateItemTag();
	 lpas = CreateAppSetting(name, read);
	 lpIt->lpSetting = lpas;
	 lpIt->lpAppl = appl;
	 tis.u.item.lParam = (LPARAM)lpIt;

	 /* convert the value for 'dosver or winver' to human readable form */
	 description = getDescriptionFromVersion(getWinVersions(), read);
	 if(!description)
	 {
	   description = getDescriptionFromVersion(getDOSVersions(), read);
	   if(!description)
	     description = "Not found";
	 }

	 sprintf(itemtext, "%s - %s", name, description);
	 tis.u.item.pszText = itemtext;

	 TreeView_InsertItem(hwndTV,&tis);
	 i++; size = 255; readSize = 255;
       }
       RegCloseKey(key);
     } else
     {
       WINE_TRACE("no version section found\n");
     }
  }
}

static VOID SetEnabledAppControls(HWND dialog)
{
}

static VOID UpdateComboboxes(HWND hDlg, LPAPPL lpAppl)
{
  int i;
  const VERSION_DESC *pVer = NULL;

  /* retrieve the registry values for this application */
  char *curWinVer = getConfigValue(lpAppl->lpcVersionSection, "Windows", "");
  char *curDOSVer = getConfigValue(lpAppl->lpcVersionSection, "DOS", "");

  if(curWinVer) WINE_TRACE("curWinVer is '%s'\n", curWinVer);
  else WINE_TRACE("curWinVer is null\n");
  if(curDOSVer) WINE_TRACE("curDOSVer is '%s'\n", curDOSVer);
  else WINE_TRACE("curDOSVer is null\n");

  /* normalize the version strings */
  if(strlen(curWinVer) != 0)
  {
    if ((pVer = getWinVersions ()))
    {
      WINE_TRACE("Windows version\n");
      for (i = 0; *pVer->szVersion || *pVer->szDescription; i++, pVer++)
      {
	WINE_TRACE("pVer->szVersion == %s\n", pVer->szVersion);
	if (!strcasecmp (pVer->szVersion, curWinVer))
	{
	  SendDlgItemMessage (hDlg, IDC_WINVER, CB_SETCURSEL,
			      (WPARAM) i, 0);
	  WINE_TRACE("match with %s\n", pVer->szVersion);
	}
      }
    }
  } else /* clear selection */
  {
    WINE_TRACE("setting winver to nothing\n");
    SendDlgItemMessage (hDlg, IDC_WINVER, CB_SETCURSEL,
			-1, 0);
  }

  if(strlen(curDOSVer) != 0)
  {
    if ((pVer = getDOSVersions ()))
    {
      WINE_TRACE("DOS version\n");
      for (i = 0; *pVer->szVersion || *pVer->szDescription; i++, pVer++)
      {
	WINE_TRACE("pVer->szVersion == %s\n", pVer->szVersion);
	if (!strcasecmp (pVer->szVersion, curDOSVer))
	{
	  SendDlgItemMessage (hDlg, IDC_DOSVER, CB_SETCURSEL,
			      (WPARAM) i, 0);
	  WINE_TRACE("match with %s\n", pVer->szVersion);
	}
      }
    }
  } else
  {
    WINE_TRACE("setting dosver to nothing\n");
    SendDlgItemMessage (hDlg, IDC_DOSVER, CB_SETCURSEL,
			-1, 0);
  }

  if(curWinVer) free(curWinVer);
  if(curDOSVer) free(curDOSVer);
}

void
initAppDlgComboboxes (HWND hDlg)
{
  int i;
  const VERSION_DESC *pVer = NULL;

  if ((pVer = getWinVersions ()))
  {
    for (i = 0; *pVer->szVersion || *pVer->szDescription; i++, pVer++)
    {
      SendDlgItemMessage (hDlg, IDC_WINVER, CB_ADDSTRING,
			  0, (LPARAM) pVer->szDescription);
    }
  }
  if ((pVer = getDOSVersions ()))
  {
    for (i = 0; *pVer->szVersion || *pVer->szDescription ; i++, pVer++)
    {
      SendDlgItemMessage (hDlg, IDC_DOSVER, CB_ADDSTRING,
			  0, (LPARAM) pVer->szDescription);
    }
  }
}


static VOID OnInitAppDlg(HWND hDlg)
{
  HWND hwndTV;
  LPAPPL lpAppl;
  HKEY applKey;
  int i;
  DWORD size;
  char appl [255];
  char lpcVersionKey [255];
  FILETIME ft;

  hwndTV = GetDlgItem(hDlg,IDC_APP_TREEVIEW);
  lpAppl = CreateAppl(TRUE, "Global Settings", "Version");
  LoadAppSettings(lpAppl, hDlg, hwndTV);
	
  /*And now the application specific stuff:*/
  if (RegOpenKey(configKey, "AppDefaults", &applKey) == ERROR_SUCCESS)
  {
    i = 0;
    size = 255;
    while (RegEnumKeyEx(applKey, i, appl, &size, NULL, NULL, NULL, &ft) == ERROR_SUCCESS)
    {
      sprintf(lpcVersionKey, "AppDefaults\\%s\\Version", appl);
      lpAppl = CreateAppl(FALSE, appl, lpcVersionKey);
      LoadAppSettings(lpAppl, hDlg, hwndTV);
      i++; size = 255;
    }
    RegCloseKey(applKey);
  }
  SetEnabledAppControls(hDlg);
}

static VOID OnTreeViewChangeItem(HWND hDlg, HWND hTV)
{
  TVITEM ti;
  LPITEMTAG lpit;

  ti.mask = TVIF_PARAM;
  ti.hItem = TreeView_GetSelection(hTV);
  if (TreeView_GetItem (hTV, &ti))
  {
    lpit = (LPITEMTAG) ti.lParam;
    if (lpit->lpAppl)
    {
      WINE_TRACE("lpit->lpAppl is non-null\n");
      /* update comboboxes to reflect settings for this app */
      UpdateComboboxes(hDlg, lpit->lpAppl);
    } else
    {
      WINE_TRACE("lpit->lpAppl is null\n");
    }
  }
}

static VOID OnTreeViewDeleteItem(NMTREEVIEW* nmt)
{
  FreeItemTag((LPITEMTAG)(nmt->itemOld.lParam));
}

static VOID OnAddApplicationClick(HWND hDlg)
{
  char szFileTitle [255];
  char szFile [255];
  char lpcVersionKey [255];

  TVINSERTSTRUCT tis;
  LPITEMTAG lpit;
  OPENFILENAME ofn = { sizeof(OPENFILENAME),
		       0, /*hInst*/0, "Wine Programs (*.exe,*.exe.so)\0*.exe;*.exe.so\0", NULL, 0, 0, NULL,
		       0, NULL, 0, NULL, NULL,
		       OFN_SHOWHELP, 0, 0, NULL, 0, NULL };

  ofn.lpstrFileTitle = szFileTitle;
  ofn.lpstrFileTitle[0] = '\0';
  ofn.nMaxFileTitle = sizeof(szFileTitle);
  ofn.lpstrFile = szFile;
  ofn.lpstrFile[0] = '\0';
  ofn.nMaxFile = sizeof(szFile);

  if (GetOpenFileName(&ofn))
  {
    tis.hParent = NULL;
    tis.hInsertAfter = TVI_LAST;
    tis.u.item.mask = TVIF_TEXT | TVIF_PARAM;
    tis.u.item.pszText = szFileTitle;
    lpit = CreateItemTag();
    sprintf(lpcVersionKey, "AppDefaults\\%s\\Version", szFileTitle);
    lpit->lpAppl = CreateAppl(FALSE, szFileTitle, lpcVersionKey);
    tis.u.item.lParam = (LPARAM)lpit;
    TreeView_InsertItem(GetDlgItem(hDlg, IDC_APP_TREEVIEW), &tis);

    /* add the empty entries for the Version section for this app */
    setConfigValue(lpcVersionKey,NULL,NULL);
  }
}

static VOID OnRemoveApplicationClick(HWND hDlg)
{
  HWND hTV;
  TVITEM ti;
  LPITEMTAG lpit;

  hTV = GetDlgItem(hDlg, IDC_APP_TREEVIEW);
  ti.mask = TVIF_PARAM;
  ti.hItem = TreeView_GetSelection(hTV);
  if (TreeView_GetItem (hTV, &ti))
  {
    lpit = (LPITEMTAG) ti.lParam;
    if (lpit->lpAppl)
    {
      /* add transactions to remove all entries for this application */
      addTransaction(lpit->lpAppl->lpcVersionSection, NULL, ACTION_REMOVE, NULL);
      TreeView_DeleteItem(hTV,ti.hItem);
    }
  }
}

static void UpdateWinverSelection(HWND hDlg, int selection)
{
  TVITEM ti;
  LPITEMTAG lpit;
  VERSION_DESC *pVer = NULL;
  HWND hTV = GetDlgItem(hDlg, IDC_APP_TREEVIEW);

  ti.mask = TVIF_PARAM;
  ti.hItem = TreeView_GetSelection(hTV);
  if (TreeView_GetItem (hTV, &ti))
  {
    lpit = (LPITEMTAG) ti.lParam;

    if(lpit->lpAppl)
    {
      pVer = getWinVersions();

      /* if no item is selected OR if our version string is null */
      /* remove this applications setting */
      if((selection == CB_ERR) || !(*pVer[selection].szVersion))
      {
	WINE_TRACE("removing section '%s'\n", lpit->lpAppl->lpcVersionSection);
	addTransaction(lpit->lpAppl->lpcVersionSection, "Windows", ACTION_REMOVE, NULL); /* change registry entry */
      } else
      {
	WINE_TRACE("setting section '%s', key '%s', value '%s'\n", lpit->lpAppl->lpcVersionSection, "Windows", pVer[selection].szVersion);
	addTransaction(lpit->lpAppl->lpcVersionSection, "Windows", ACTION_SET, pVer[selection].szVersion); /* change registry entry */
      }

      TreeView_DeleteAllItems(hTV); /* delete all items from the treeview */
      OnInitAppDlg(hDlg);
    }
  }
}

static void UpdateDosverSelection(HWND hDlg, int selection)
{
  TVITEM ti;
  LPITEMTAG lpit;
  VERSION_DESC *pVer = NULL;
  HWND hTV = GetDlgItem(hDlg, IDC_APP_TREEVIEW);

  ti.mask = TVIF_PARAM;
  ti.hItem = TreeView_GetSelection(hTV);
  if (TreeView_GetItem (hTV, &ti))
  {
    lpit = (LPITEMTAG) ti.lParam;

    if(lpit->lpAppl)
    {
      pVer = getDOSVersions();

      /* if no item is selected OR if our version string is null */
      /* remove this applications setting */
      if((selection == CB_ERR) || !(*pVer[selection].szVersion))
      {
	WINE_TRACE("removing section '%s'\n", lpit->lpAppl->lpcVersionSection);
	addTransaction(lpit->lpAppl->lpcVersionSection, "DOS", ACTION_REMOVE, NULL); /* change registry entry */
      } else
      {
	WINE_TRACE("setting section '%s', key '%s', value '%s'\n", lpit->lpAppl->lpcVersionSection, "DOS", pVer[selection].szVersion);
	addTransaction(lpit->lpAppl->lpcVersionSection, "DOS", ACTION_SET, pVer[selection].szVersion); /* change registry entry */
      }

      TreeView_DeleteAllItems(hTV); /* delete all items from the treeview */
      OnInitAppDlg(hDlg);
    }
  }
}

INT_PTR CALLBACK
AppDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
  int selection;
  switch (uMsg)
  {
  case WM_INITDIALOG:
    OnInitAppDlg(hDlg);
    initAppDlgComboboxes(hDlg);
    break;  
  case WM_NOTIFY:
    switch (((LPNMHDR)lParam)->code) {
    case TVN_SELCHANGED: {
      switch(LOWORD(wParam)) {
      case IDC_APP_TREEVIEW:
	OnTreeViewChangeItem(hDlg, GetDlgItem(hDlg,IDC_APP_TREEVIEW));
	break;
      }
    }
      break;
    case TVN_DELETEITEM:
      OnTreeViewDeleteItem ((LPNMTREEVIEW)lParam);
      break;
    }
    break;
  case WM_COMMAND:
    switch(HIWORD(wParam)) {
    case CBN_SELCHANGE:
      switch(LOWORD(wParam)) {
      case IDC_WINVER:
	selection = SendDlgItemMessage( hDlg, IDC_WINVER, CB_GETCURSEL, 0, 0);
	UpdateWinverSelection(hDlg, selection);
	break;
      case IDC_DOSVER:
	selection = SendDlgItemMessage( hDlg, IDC_DOSVER, CB_GETCURSEL, 0, 0);
	UpdateDosverSelection(hDlg, selection);
	break;
      }
    case BN_CLICKED:
      switch(LOWORD(wParam)) {
      case IDC_APP_ADDAPP:
	OnAddApplicationClick(hDlg);
	break;
      case IDC_APP_REMOVEAPP:
	OnRemoveApplicationClick(hDlg);
	break;
      }
      break;
    }
    break;
  }

  return 0;
}
