/*
 * Copyright (c) 2000, Red Hat, Inc.
 * Copyright (c) 2005-2006, Tom N Harris <telliamed@whoopdedo.org>.
 *
 *     This program is free software; you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation; either version 2 of the License, or
 *     (at your option) any later version.
 *
 *     A copy of the GNU General Public License can be found at
 *     http://www.gnu.org/
 *
 * Written by Andrej Borsenkow <Andrej.Borsenkow@mow.siemens.ru>
 * based on work and suggestions of DJ Delorie
 * Written by Tom N Harris <telliamed@whoopdedo.org>
 *
 */

#include "win32.h"
#include <shlobj.h>

#include "Dirs.h"
#include "cString.h"
#include "resource.h"
#include "globals.h"
#include "dark.h"

#include "ControlAdjuster.h"
#include "PropSheet.h"

#include "Installer.h"


using namespace Setup;
using namespace std;

/*
  Sizing information.
 */
static ControlAdjuster::ControlInfo GameDirControlsInfo[] = {
	{IDC_DIR_T1_GROUP, 		CP_STRETCH, CP_CENTER},
	{IDC_DIR_T1_BROWSE,		CP_RIGHT,   CP_CENTER},
	{IDC_DIR_T1,			CP_STRETCH, CP_CENTER},
	{IDC_DIR_T2_GROUP, 		CP_STRETCH, CP_CENTER},
	{IDC_DIR_T2_BROWSE,		CP_RIGHT,   CP_CENTER},
	{IDC_DIR_T2,			CP_STRETCH, CP_CENTER},
	{IDC_DIR_SS2_GROUP, 		CP_STRETCH, CP_CENTER},
	{IDC_DIR_SS2_BROWSE,		CP_RIGHT,   CP_CENTER},
	{IDC_DIR_SS2,			CP_STRETCH, CP_CENTER},
	{0, CP_LEFT, CP_TOP}
};

GameDirPage::GameDirPage(Installer & i)
	: m_installer(i), m_inputs(DARKGAME_ALL), m_initted(0)
{
	m_sizeProcessor.addControlInfo(GameDirControlsInfo);
}

static int CALLBACK
browse_cb(HWND h, UINT msg, LPARAM lp, LPARAM data)
{
	switch (msg)
	{
	case BFFM_INITIALIZED:
		if (data)
			::SendMessage(h, BFFM_SETSELECTION, TRUE, data);
		break;
	}
	return 0;
}

void
GameDirPage::browseDirectory(int which)
{
	String strPath = getDlgItemText(which);
	String strTitle = String::Load(IDS_DIR_PROMPT);
	TCHAR name[MAX_PATH];
	LPITEMIDLIST pidl;
	BROWSEINFO bi;
	memset(&bi, 0, sizeof(bi));
	bi.hwndOwner = getHWND();
	bi.pszDisplayName = name;
	bi.lpszTitle = strTitle.c_str();
	bi.ulFlags = BIF_RETURNONLYFSDIRS;
	bi.lpfn = browse_cb;
	bi.lParam = reinterpret_cast<LPARAM>(strPath.c_str());
	pidl = ::SHBrowseForFolder(&bi);
	if (pidl)
	{
		if (::SHGetPathFromIDList(pidl, name))
		{
			setDlgItemText(which, name);
		}
	}
}

bool
GameDirPage::onMessageCmd(int id, HWND hwndctl, UINT code)
{
	if (code == EN_CHANGE)
	{
		enableNext(validateDirs());
	}

	if (code == BN_CLICKED)
	{
		switch (id)
		{
		case IDC_DIR_T1_BROWSE:
			browseDirectory(IDC_DIR_T1);
			break;
		case IDC_DIR_T2_BROWSE:
			browseDirectory(IDC_DIR_T2);
			break;
		case IDC_DIR_SS2_BROWSE:
			browseDirectory(IDC_DIR_SS2);
			break;
		default:
			return false;
		}
		enableNext(validateDirs());
		return true;
	}
	return false;
}

bool
GameDirPage::create()
{
  return PropertyPage::create(IDD_LOCAL_DIR);
}

void
GameDirPage::onInit()
{
}

void
GameDirPage::onActivate()
{
	int games = m_installer.InstallGames();
	if (games & DARKGAME_T1)
		showInput(DARKGAME_T1);
	else
		hideInput(DARKGAME_T1);
	if (games & DARKGAME_T2)
		showInput(DARKGAME_T2);
	else
		hideInput(DARKGAME_T2);
	if (games & DARKGAME_SS2)
		showInput(DARKGAME_SS2);
	else
		hideInput(DARKGAME_SS2);

	enableNext(validateDirs());
}

long
GameDirPage::onNext()
{
	String dir;
	if (m_inputs & DARKGAME_T1)
	{
		dir = getDlgItemText(IDC_DIR_T1);
		m_installer.SetDestDirectory(DARKGAME_T1, dir);
	}
	if (m_inputs & DARKGAME_T2)
	{
		dir = getDlgItemText(IDC_DIR_T2);
		m_installer.SetDestDirectory(DARKGAME_T2, dir);
	}
	if (m_inputs & DARKGAME_SS2)
	{
		dir = getDlgItemText(IDC_DIR_SS2);
		m_installer.SetDestDirectory(DARKGAME_SS2, dir);
	}

	if (! m_installer.CollectFiles(getHWND()))
	{
		return AbortPageChange;
	}

	return NextPage;
}

long
GameDirPage::onBack()
{
  return PreviousPage;
}

bool
GameDirPage::validateDirs()
{
	String dir;
	DWORD attr;

	if (m_inputs & DARKGAME_T1)
	{
		dir = getDlgItemText(IDC_DIR_T1);
		if (dir.empty())
			return false;
		attr = ::GetFileAttributes(dir.c_str());
		if ((attr == INVALID_FILE_ATTRIBUTES)
		 || (0 == (attr & FILE_ATTRIBUTE_DIRECTORY)))
			return false;
	}

	if (m_inputs & DARKGAME_T2)
	{
		dir = getDlgItemText(IDC_DIR_T2);
		if (dir.empty())
			return false;
		attr = ::GetFileAttributes(dir.c_str());
		if ((attr == INVALID_FILE_ATTRIBUTES)
		 || (0 == (attr & FILE_ATTRIBUTE_DIRECTORY)))
			return false;
	}

	if (m_inputs & DARKGAME_SS2)
	{
		dir = getDlgItemText(IDC_DIR_SS2);
		if (dir.empty())
			return false;
		attr = ::GetFileAttributes(dir.c_str());
		if ((attr == INVALID_FILE_ATTRIBUTES)
		 || (0 == (attr & FILE_ATTRIBUTE_DIRECTORY)))
			return false;
	}

	return true;
}

#define MOVEDLGITEM(i,x,y)	\
	r = getDlgItemRect((i)); \
	r.left += (x); r.right += (x); r.top += (y); r.bottom += (y); \
	::SetWindowPos(getDlgItem((i)), 0, r.left, r.top, r.width(), r.height(), \
	SWP_NOACTIVATE | SWP_NOZORDER);

void 
GameDirPage::showInput(int which)
{
	int group, edit, btn;
	switch (which)
	{
	default:
		return;
	case DARKGAME_T1:
		group = IDC_DIR_T1_GROUP;
		edit = IDC_DIR_T1;
		btn = IDC_DIR_T1_BROWSE;
		break;
	case DARKGAME_T2:
		group = IDC_DIR_T2_GROUP;
		edit = IDC_DIR_T2;
		btn = IDC_DIR_T2_BROWSE;
		break;
	case DARKGAME_SS2:
		group = IDC_DIR_SS2_GROUP;
		edit = IDC_DIR_SS2;
		btn = IDC_DIR_SS2_BROWSE;
		break;
	}

	if (! (m_initted & which))
	{
		setDlgItemText(edit, LocateGameDir(which));
		m_initted |= which;
	}

	if (m_inputs & which)
		return;

	::ShowWindow(getDlgItem(group), SW_SHOW);
	::ShowWindow(getDlgItem(edit), SW_SHOW);
	::ShowWindow(getDlgItem(btn), SW_SHOW);
	m_inputs |= which;

	int dy = RECTWrapper(getDlgItemRect(group)).height() + 8;
	RECTWrapper r;
	switch (group)
	{
	case IDC_DIR_T1_GROUP:
		dy = dy - dy/2;
		MOVEDLGITEM(IDC_DIR_T2_GROUP,0,dy)
		MOVEDLGITEM(IDC_DIR_T2,0,dy)
		MOVEDLGITEM(IDC_DIR_T2_BROWSE,0,dy)
		MOVEDLGITEM(IDC_DIR_SS2_GROUP,0,dy)
		MOVEDLGITEM(IDC_DIR_SS2,0,dy)
		MOVEDLGITEM(IDC_DIR_SS2_BROWSE,0,dy)
		break;
	case IDC_DIR_T2_GROUP:
		{
		int dy2 = -(dy/2);
		dy += dy2;
		MOVEDLGITEM(IDC_DIR_T1_GROUP,0,dy2)
		MOVEDLGITEM(IDC_DIR_T1,0,dy2)
		MOVEDLGITEM(IDC_DIR_T1_BROWSE,0,dy2)
		MOVEDLGITEM(IDC_DIR_SS2_GROUP,0,dy)
		MOVEDLGITEM(IDC_DIR_SS2,0,dy)
		MOVEDLGITEM(IDC_DIR_SS2_BROWSE,0,dy)
		break;
		}
	case IDC_DIR_SS2_GROUP:
		dy = -(dy/2);
		MOVEDLGITEM(IDC_DIR_T1_GROUP,0,dy)
		MOVEDLGITEM(IDC_DIR_T1,0,dy)
		MOVEDLGITEM(IDC_DIR_T1_BROWSE,0,dy)
		MOVEDLGITEM(IDC_DIR_T2_GROUP,0,dy)
		MOVEDLGITEM(IDC_DIR_T2,0,dy)
		MOVEDLGITEM(IDC_DIR_T2_BROWSE,0,dy)
		break;
	}
}

void 
GameDirPage::hideInput(int which)
{
	int group, edit, btn;
	switch (which)
	{
	default:
		return;
	case DARKGAME_T1:
		group = IDC_DIR_T1_GROUP;
		edit = IDC_DIR_T1;
		btn = IDC_DIR_T1_BROWSE;
		break;
	case DARKGAME_T2:
		group = IDC_DIR_T2_GROUP;
		edit = IDC_DIR_T2;
		btn = IDC_DIR_T2_BROWSE;
		break;
	case DARKGAME_SS2:
		group = IDC_DIR_SS2_GROUP;
		edit = IDC_DIR_SS2;
		btn = IDC_DIR_SS2_BROWSE;
		break;
	}

	if (! (m_inputs & which))
		return;

	::ShowWindow(getDlgItem(group), SW_HIDE);
	::ShowWindow(getDlgItem(edit), SW_HIDE);
	::ShowWindow(getDlgItem(btn), SW_HIDE);
	m_inputs &= ~which;

	int dy = RECTWrapper(getDlgItemRect(group)).height() + 8;
	RECTWrapper r;
	switch (group)
	{
	case IDC_DIR_T1_GROUP:
		dy = -(dy - dy/2);
		MOVEDLGITEM(IDC_DIR_T2_GROUP,0,dy)
		MOVEDLGITEM(IDC_DIR_T2,0,dy)
		MOVEDLGITEM(IDC_DIR_T2_BROWSE,0,dy)
		MOVEDLGITEM(IDC_DIR_SS2_GROUP,0,dy)
		MOVEDLGITEM(IDC_DIR_SS2,0,dy)
		MOVEDLGITEM(IDC_DIR_SS2_BROWSE,0,dy)
		break;
	case IDC_DIR_T2_GROUP:
		{
		int dy2 = dy/2;
		dy = -(dy - dy2);
		MOVEDLGITEM(IDC_DIR_T1_GROUP,0,dy2)
		MOVEDLGITEM(IDC_DIR_T1,0,dy2)
		MOVEDLGITEM(IDC_DIR_T1_BROWSE,0,dy2)
		MOVEDLGITEM(IDC_DIR_SS2_GROUP,0,dy)
		MOVEDLGITEM(IDC_DIR_SS2,0,dy)
		MOVEDLGITEM(IDC_DIR_SS2_BROWSE,0,dy)
		break;
		}
	case IDC_DIR_SS2_GROUP:
		dy = dy/2;
		MOVEDLGITEM(IDC_DIR_T1_GROUP,0,dy)
		MOVEDLGITEM(IDC_DIR_T1,0,dy)
		MOVEDLGITEM(IDC_DIR_T1_BROWSE,0,dy)
		MOVEDLGITEM(IDC_DIR_T2_GROUP,0,dy)
		MOVEDLGITEM(IDC_DIR_T2,0,dy)
		MOVEDLGITEM(IDC_DIR_T2_BROWSE,0,dy)
		break;
	}

}

