/**
 * name:		SaveInitialDir
 * desc:		save the last vCard directory from database
 *				pszInitialDir	- buffer to store the initial dir to (size must be MAX_PATH)
 * return:		nothing
 **/
static void SaveInitialDir(LPSTR pszInitialDir)
{
	CHAR szRelative[MAX_PATH];
	LPSTR p;

	if (p = mir_strrchr(pszInitialDir, '\\')) {
		*p = 0;
		if ( PathToRelative(pszInitialDir, szRelative))
			db_set_s(0, MODNAME, "vCardPath", szRelative);
		else
			db_set_s(0, MODNAME, "vCardPath", pszInitialDir);
		*p = '\\';
	}	
}
INT_PTR CALLBACK SaveOptsDlgProc(OptPageControl *controls, int controlsSize, char *module, HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	TCHAR tmp[1024];

	switch (msg) {
	case WM_INITDIALOG:
		TranslateDialogDefault(hwndDlg);

		for (int i = 0; i < controlsSize; i++) {
			OptPageControl *ctrl = &controls[i];

			if (GetDlgItem(hwndDlg, ctrl->nID) == NULL)
				continue;

			switch (ctrl->type) {
			case CONTROL_CHECKBOX:
				CheckDlgButton(hwndDlg, ctrl->nID, db_get_b(NULL, module, ctrl->setting, ctrl->dwDefValue) == 1 ? BST_CHECKED : BST_UNCHECKED);
				break;

			case CONTROL_SPIN:
				SendDlgItemMessage(hwndDlg, ctrl->nIDSpin, UDM_SETBUDDY, (WPARAM)GetDlgItem(hwndDlg, ctrl->nID), 0);
				SendDlgItemMessage(hwndDlg, ctrl->nIDSpin, UDM_SETRANGE, 0, MAKELONG(ctrl->max, ctrl->min));
				SendDlgItemMessage(hwndDlg, ctrl->nIDSpin, UDM_SETPOS, 0, MAKELONG(db_get_w(NULL, module, ctrl->setting, ctrl->dwDefValue), 0));
				break;

			case CONTROL_COLOR:
				SendDlgItemMessage(hwndDlg, ctrl->nID, CPM_SETCOLOUR, 0, (COLORREF)db_get_dw(NULL, module, ctrl->setting, ctrl->dwDefValue));
				break;

			case CONTROL_RADIO:
				CheckDlgButton(hwndDlg, ctrl->nID, db_get_w(NULL, module, ctrl->setting, ctrl->dwDefValue) == ctrl->value ? BST_CHECKED : BST_UNCHECKED);
				break;

			case CONTROL_COMBO:
				SendDlgItemMessage(hwndDlg, ctrl->nID, CB_SETCURSEL, db_get_w(NULL, module, ctrl->setting, ctrl->dwDefValue), 0);
				break;

			case CONTROL_PROTOCOL_LIST:
				{
					// Fill list view
					HWND hwndProtocols = GetDlgItem(hwndDlg, ctrl->nID);
					LVCOLUMN lvc;
					LVITEM lvi;

					ListView_SetExtendedListViewStyle(hwndProtocols, LVS_EX_CHECKBOXES);

					memset(&lvc, 0, sizeof(lvc));
					lvc.mask = LVCF_FMT;
					lvc.fmt = LVCFMT_IMAGE | LVCFMT_LEFT;
					ListView_InsertColumn(hwndProtocols, 0, &lvc);

					memset(&lvi, 0, sizeof(lvi));
					lvi.mask = LVIF_TEXT | LVIF_PARAM;
					lvi.iSubItem = 0;
					lvi.iItem = 1000;

					int count;
					PROTOACCOUNT **protos;
					Proto_EnumAccounts(&count, &protos);

					for (int k = 0; k < count; k++) {
						PROTOACCOUNT *p = protos[k];
						if (p->szModuleName == NULL || p->szModuleName[0] == '\0')
							continue;

						if (ctrl->allowProtocol != NULL && !ctrl->allowProtocol(p->szModuleName))
							continue;

						char *setting = (char *)mir_alloc(128 * sizeof(char));
						mir_snprintf(setting, 128, ctrl->setting, p->szModuleName);

						BOOL show = (BOOL)db_get_b(NULL, module, setting, ctrl->dwDefValue);

						lvi.lParam = (LPARAM)setting;
						lvi.pszText = p->tszAccountName;
						lvi.iItem = ListView_InsertItem(hwndProtocols, &lvi);
						ListView_SetItemState(hwndProtocols, lvi.iItem, INDEXTOSTATEIMAGEMASK(show ? 2 : 1), LVIS_STATEIMAGEMASK);
					}

					ListView_SetColumnWidth(hwndProtocols, 0, LVSCW_AUTOSIZE);
					ListView_Arrange(hwndProtocols, LVA_ALIGNLEFT | LVA_ALIGNTOP);
				}
				break;

			case CONTROL_TEXT:
				SetDlgItemText(hwndDlg, ctrl->nID, MyDBGetContactSettingTString(NULL, module, ctrl->setting, tmp, 1024, ctrl->tszDefValue == NULL ? NULL : TranslateTS(ctrl->tszDefValue)));
				SendDlgItemMessage(hwndDlg, ctrl->nID, EM_LIMITTEXT, min(ctrl->max <= 0 ? 1024 : ctrl->max, 1024), 0);
				break;

			case CONTROL_INT:
				SetDlgItemInt(hwndDlg, ctrl->nID, db_get_dw(NULL, module, ctrl->setting, ctrl->dwDefValue), ctrl->min <= 0);
				SendDlgItemMessage(hwndDlg, ctrl->nID, EM_LIMITTEXT, 9, 0);
				break;

			case CONTROL_FILE:
				MyDBGetContactSettingTString(NULL, module, ctrl->setting, tmp, 1024, ctrl->tszDefValue == NULL ? NULL : ctrl->tszDefValue);
				{
					TCHAR abs[1024];
					PathToAbsolute(abs, 1024, tmp);
					SetDlgItemText(hwndDlg, ctrl->nID, abs);
				}
				SendDlgItemMessage(hwndDlg, ctrl->nID, EM_LIMITTEXT, min(ctrl->max <= 0 ? 1024 : ctrl->max, 1024), 0);
				break;

			case CONTROL_COMBO_TEXT:
				MyDBGetContactSettingTString(NULL, module, ctrl->setting, tmp, 1024, ctrl->tszDefValue == NULL ? NULL : TranslateTS(ctrl->tszDefValue));
				SendDlgItemMessage(hwndDlg, ctrl->nID, CB_SELECTSTRING, 0, (WPARAM)tmp);
				break;

			case CONTROL_COMBO_ITEMDATA:
				MyDBGetContactSettingTString(NULL, module, ctrl->setting, tmp, 1024, ctrl->tszDefValue == NULL ? NULL : TranslateTS(ctrl->tszDefValue));
				{
					int count = SendDlgItemMessage(hwndDlg, ctrl->nID, CB_GETCOUNT, 0, 0);
					int k;
					for (k = 0; k < count; k++) {
						TCHAR *id = (TCHAR *)SendDlgItemMessage(hwndDlg, ctrl->nID, CB_GETITEMDATA, (WPARAM)k, 0);
						if (mir_tstrcmp(id, tmp) == 0)
							break;
					}
					if (k < count)
						SendDlgItemMessage(hwndDlg, ctrl->nID, CB_SETCURSEL, k, 0);
				}
				break;
			}
		}
		break;

	case WM_COMMAND:
		for (int i = 0; i < controlsSize; i++) {
			OptPageControl *ctrl = &controls[i];

			if (LOWORD(wParam) == ctrl->nID) {
				switch (ctrl->type) {
				case CONTROL_TEXT:
				case CONTROL_SPIN:
				case CONTROL_INT:
					// Don't make apply enabled during buddy set
					if (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())
						return 0;

					break;

				case CONTROL_COMBO_ITEMDATA:
				case CONTROL_COMBO_TEXT:
				case CONTROL_COMBO:
					if (HIWORD(wParam) != CBN_SELCHANGE || (HWND)lParam != GetFocus())
						return 0;
					break;
				}

				SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
			}
		}
		break;

	case WM_NOTIFY:
		{
			LPNMHDR lpnmhdr = (LPNMHDR)lParam;
			if (lpnmhdr->idFrom == 0 && lpnmhdr->code == PSN_APPLY) {
				for (int i = 0; i < controlsSize; i++) {
					OptPageControl *ctrl = &controls[i];

					if (GetDlgItem(hwndDlg, ctrl->nID) == NULL)
						continue;

					switch (ctrl->type) {
					case CONTROL_CHECKBOX:
						db_set_b(NULL, module, ctrl->setting, (BYTE)IsDlgButtonChecked(hwndDlg, ctrl->nID));
						break;

					case CONTROL_SPIN:
						db_set_w(NULL, module, ctrl->setting, (WORD)SendDlgItemMessage(hwndDlg, ctrl->nIDSpin, UDM_GETPOS, 0, 0));
						break;

					case CONTROL_COLOR:
						db_set_dw(NULL, module, ctrl->setting, (DWORD)SendDlgItemMessage(hwndDlg, ctrl->nID, CPM_GETCOLOUR, 0, 0));
						break;

					case CONTROL_RADIO:
						if (IsDlgButtonChecked(hwndDlg, ctrl->nID))
							db_set_w(NULL, module, ctrl->setting, (BYTE)ctrl->value);
						break;

					case CONTROL_COMBO:
						db_set_w(NULL, module, ctrl->setting, (WORD)SendDlgItemMessage(hwndDlg, ctrl->nID, CB_GETCURSEL, 0, 0));
						break;

					case CONTROL_PROTOCOL_LIST:
						{
							LVITEM lvi = { 0 };
							lvi.mask = (UINT)LVIF_PARAM;

							HWND hwndProtocols = GetDlgItem(hwndDlg, ctrl->nID);
							int count = ListView_GetItemCount(hwndProtocols);
							for (int k = 0; k < count; k++) {
								lvi.iItem = k;
								ListView_GetItem(hwndProtocols, &lvi);

								char *setting = (char *)lvi.lParam;
								db_set_b(NULL, module, setting, (BYTE)ListView_GetCheckState(hwndProtocols, k));
							}
						}
						break;

					case CONTROL_TEXT:
						GetDlgItemText(hwndDlg, ctrl->nID, tmp, _countof(tmp));
						db_set_ts(NULL, module, ctrl->setting, tmp);
						break;

					case CONTROL_INT:
						BOOL trans;
						{
							int val = GetDlgItemInt(hwndDlg, ctrl->nID, &trans, ctrl->min <= 0);
							if (!trans)
								val = ctrl->dwDefValue;
							if (ctrl->max != 0)
								val = min(val, ctrl->max);
							if (ctrl->min != 0)
								val = max(val, ctrl->min);
							db_set_dw(NULL, module, ctrl->setting, val);
						}
						break;

					case CONTROL_FILE:
						GetDlgItemText(hwndDlg, ctrl->nID, tmp, _countof(tmp));
						{
							TCHAR rel[1024];
							PathToRelative(rel, 1024, tmp);
							db_set_ts(NULL, module, ctrl->setting, rel);
						}
						break;

					case CONTROL_COMBO_TEXT:
						GetDlgItemText(hwndDlg, ctrl->nID, tmp, _countof(tmp));
						db_set_ts(NULL, module, ctrl->setting, tmp);
						break;

					case CONTROL_COMBO_ITEMDATA:
						int sel = SendDlgItemMessage(hwndDlg, ctrl->nID, CB_GETCURSEL, 0, 0);
						db_set_ts(NULL, module, ctrl->setting, (TCHAR *)SendDlgItemMessage(hwndDlg, ctrl->nID, CB_GETITEMDATA, (WPARAM)sel, 0));
						break;
					}

					LoadOpt(ctrl, module);
				}

				return TRUE;
			}
			else if (lpnmhdr->idFrom != 0 && lpnmhdr->code == LVN_ITEMCHANGED) {
				// Changed for protocols
				for (int i = 0; i < controlsSize; i++) {
					OptPageControl *ctrl = &controls[i];

					if (ctrl->type == CONTROL_PROTOCOL_LIST && ctrl->nID == lpnmhdr->idFrom) {
						NMLISTVIEW *nmlv = (NMLISTVIEW *)lParam;

						if (IsWindowVisible(GetDlgItem(hwndDlg, ctrl->nID)) && ((nmlv->uNewState ^ nmlv->uOldState) & LVIS_STATEIMAGEMASK))
							SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);

						break;
					}
				}
			}
		}
		break;

	case WM_DESTROY:
		for (int i = 0; i < controlsSize; i++) {
			OptPageControl *ctrl = &controls[i];

			if (GetDlgItem(hwndDlg, ctrl->nID) == NULL)
				continue;

			switch (ctrl->type) {
			case CONTROL_PROTOCOL_LIST:
				LVITEM lvi = { 0 };
				lvi.mask = (UINT)LVIF_PARAM;

				HWND hwndProtocols = GetDlgItem(hwndDlg, ctrl->nID);
				int count = ListView_GetItemCount(hwndProtocols);
				for (i = 0; i < count; i++) {
					lvi.iItem = i;
					ListView_GetItem(hwndProtocols, &lvi);
					mir_free((char *)lvi.lParam);
				}
				break;
			}
		}
		break;
	}

	return 0;
}