/*
Copyright (c) 2005 Victor Pavlychko (nullbyte@sotline.net.ua)
Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.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 version 2
of the License.

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "stdafx.h"

/////////////////////////////////////////////////////////////////////////////////////////
// Basic options page class

class CBaseOptsDlg : public CDlgBase
{
protected:
	CBaseOptsDlg(int iDlgId) :
		CDlgBase(g_plugin, iDlgId)
	{
		m_OnFinishWizard = Callback(this, &CBaseOptsDlg::OnFinish);
	}

	void OnFinish(void *)
	{
		WindowList_BroadcastAsync(g_hNewstoryLogs, NSM_SET_OPTIONS, 0, 0);
	}
};

/////////////////////////////////////////////////////////////////////////////////////////
// General options dialog

class CGeneralOptsDlg : public CBaseOptsDlg
{
	CCtrlCheck chkGrouping, chkVScroll, chkDrawEdge, chkSortOrder, chkHppCompat;
	CCtrlCheck chkShowType, chkShowDirection;

public:
	CGeneralOptsDlg() :
		CBaseOptsDlg(IDD_OPT_ADVANCED),
		chkVScroll(this, IDC_VSCROLL),
		chkShowType(this, IDC_SHOW_TYPE),
		chkDrawEdge(this, IDC_DRAWEDGE),
		chkGrouping(this, IDC_GROUPING),
		chkHppCompat(this, IDC_HPP_COMPAT),
		chkSortOrder(this, IDC_SORT_ASCENDING),
		chkShowDirection(this, IDC_SHOW_DIRECTION)
	{
		CreateLink(chkVScroll, g_plugin.bOptVScroll);
		CreateLink(chkShowType, g_bShowType);
		CreateLink(chkGrouping, g_bOptGrouping);
		CreateLink(chkDrawEdge, g_bOptDrawEdge);
		CreateLink(chkHppCompat, g_bOptHppCompat);
		CreateLink(chkShowDirection, g_bShowDirection);

		CreateLink(chkSortOrder, g_plugin.bSortAscending);
	}

	bool OnApply() override
	{
		g_plugin.bShowType = g_bShowType;
		g_plugin.bDrawEdge = g_bOptDrawEdge;
		g_plugin.bMsgGrouping = g_bOptGrouping;
		g_plugin.bHppCompat = g_bOptHppCompat;
		g_plugin.bShowDirecction = g_bShowDirection;
		return true;
	}
};

/////////////////////////////////////////////////////////////////////////////////////////
// Template options dialog

class CTemplateOptsDlg : public CBaseOptsDlg
{
	TemplateInfo *m_curr = 0;
	ItemData m_tempItem;

	CCtrlBase preview, gpreview;
	CCtrlEdit m_edit;
	CCtrlMButton btnDiscard, bthVarHelp, btnReset;
	CCtrlTreeView m_tree;

	UI_MESSAGE_MAP(CTemplateOptsDlg, CBaseOptsDlg);
		UI_MESSAGE(UM_REDRAWLISTH, OnColorChanged);
	UI_MESSAGE_MAP_END();

	LRESULT OnColorChanged(UINT, WPARAM, LPARAM)
	{
		gpreview.SendMsg(MTM_SETBKCOLOR, g_colorTable[COLOR_BACK].cl, 0);
		return 0;
	}

public:
	CTemplateOptsDlg() :
		CBaseOptsDlg(IDD_OPT_TEMPLATES),
		m_edit(this, IDC_EDITTEMPLATE),
		m_tree(this, IDC_TEMPLATES),
		preview(this, IDC_PREVIEW),
		gpreview(this, IDC_GPREVIEW),
		btnReset(this, IDC_RESET, Skin_LoadIcon(SKINICON_OTHER_UNDO), LPGEN("Reset to default")),
		btnDiscard(this, IDC_DISCARD, g_plugin.getIcon(IDI_RESET), LPGEN("Cancel edit")),
		bthVarHelp(this, IDC_VARHELP, g_plugin.getIcon(IDI_VARHELP), LPGEN("Variables help"))
	{
		btnReset.OnClick = Callback(this, &CTemplateOptsDlg::onClick_Reset);
		btnDiscard.OnClick = Callback(this, &CTemplateOptsDlg::onClick_Discard);
		bthVarHelp.OnClick = Callback(this, &CTemplateOptsDlg::onClick_Help);

		m_edit.OnChange = Callback(this, &CTemplateOptsDlg::onChange_Edit);

		m_tree.OnSelChanged = Callback(this, &CTemplateOptsDlg::onSelChanged);
	}

	bool OnInitDialog() override
	{
		HIMAGELIST himgTree = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR32 | ILC_MASK, 1, 1);
		m_tree.SetImageList(himgTree, TVSIL_NORMAL);

		ImageList_AddIcon(himgTree, g_plugin.getIcon(IDI_TPLGROUP));

		m_tempItem.wszNick = TranslateT("Test contact");
		m_tempItem.wtext = mir_wstrdup(TranslateT("The quick brown fox jumps over the lazy dog."));
		m_tempItem.dbe.flags = DBEF_TEMPORARY | DBEF_BOOKMARK;
		m_tempItem.dbe.szModule = MODULENAME;
		m_tempItem.dbe.eventType = EVENTTYPE_MESSAGE;
		m_tempItem.dbe.timestamp = time(0);

		HTREEITEM hGroup = 0, hFirst = 0;
		const wchar_t *pwszPrevGroup = nullptr;
		for (auto &it : templates) {
			if (mir_wstrcmp(it.group, pwszPrevGroup)) {
				if (hGroup)
					m_tree.Expand(hGroup, TVE_EXPAND);

				TVINSERTSTRUCT tvis = {};
				tvis.hInsertAfter = TVI_LAST;
				tvis.item.mask = TVIF_TEXT | TVIF_STATE | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
				tvis.item.state = tvis.item.stateMask = TVIS_BOLD;
				tvis.item.pszText = TranslateW(it.group);
				tvis.item.lParam = 0;
				hGroup = m_tree.InsertItem(&tvis);

				if (!hFirst)
					hFirst = hGroup;
			}

			TVINSERTSTRUCT tvis;
			tvis.hParent = hGroup;
			tvis.hInsertAfter = TVI_LAST;
			tvis.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
			tvis.item.pszText = TranslateW(it.title);
			tvis.item.iSelectedImage = tvis.item.iImage = ImageList_AddIcon(himgTree, it.getIcon());
			tvis.item.lParam = (LPARAM)&it;
			m_tree.InsertItem(&tvis);

			pwszPrevGroup = it.group;
		}

		if (hGroup)
			m_tree.Expand(hGroup, TVE_EXPAND);

		m_tree.SelectItem(hFirst);
		m_tree.EnsureVisible(hFirst);

		WindowList_Add(g_hNewstoryWindows, m_hwnd);
		OnColorChanged(0, 0, 0);
		return true;
	}

	bool OnApply() override
	{
		if (m_curr != nullptr)
			replaceStrW(m_curr->tmpValue, m_edit.GetText());

		for (auto &it : templates) {
			if (it.tmpValue) {
				replaceStrW(it.value, it.tmpValue);
				it.tmpValue = nullptr;
			}
		}

		onChange_Edit();
		SaveTemplates();
		return true;
	}

	void OnDestroy() override
	{
		WindowList_Remove(g_hNewstoryWindows, m_hwnd);

		for (auto &it : templates)
			replaceStrW(it.tmpValue, nullptr);
	}

	void onClick_Reset(CCtrlButton *)
	{
		if (m_curr) {
			replaceStrW(m_curr->tmpValue, nullptr);
			replaceStrW(m_curr->value, nullptr);
			m_edit.SetText(TranslateW(m_curr->defvalue));
		}

		onChange_Edit();
		NotifyChange();
	}

	void onClick_Discard(CCtrlButton *)
	{
		replaceStrW(m_curr->tmpValue, 0);

		if (m_curr->value)
			m_edit.SetText(m_curr->value);
		else
			m_edit.SetText(TranslateW(m_curr->defvalue));

		onChange_Edit();
	}

	void onClick_Help(CCtrlButton *)
	{
		CMStringW wszVarHelp;
		wszVarHelp.Format(L"%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s",
			L"%%", TranslateT("simply % character"),
			L"%n", TranslateT("a \"hard\" line break (cr/lf - will break indent)"),
			L"%S", TranslateT("my nickname"),
			L"%N", TranslateT("buddy\'s nickname"),
			L"%c", TranslateT("event count"),
			L"%D", TranslateT("direction symbol"),
			L"%t", TranslateT("timestamp"),
			L"%h", TranslateT("hour (24 hour format, 0-23)"),
			L"%a", TranslateT("hour (12 hour format)"),
			L"%m", TranslateT("minute"),
			L"%s", TranslateT("second"),
			L"%o", TranslateT("month"),
			L"%d", TranslateT("day of month"),
			L"%y", TranslateT("year (4 digits)"),
			L"%w", TranslateT("day of week (Sunday, Monday... translatable)"),
			L"%p", TranslateT("AM/PM symbol"),
			L"%O", TranslateT("name of month, translatable"),
			L"%M", TranslateT("the message string itself"));
		MessageBox(m_hwnd, wszVarHelp, TranslateT("Variables help"), MB_OK);
	}

	void onChange_Edit(CCtrlEdit* = 0)
	{
		replaceStrW(m_curr->tmpValue, m_edit.GetText());

		m_tempItem.fill(int(m_curr - templates)); // copy data from template to event

		CMStringW wszText(m_tempItem.formatStringEx(m_curr->tmpValue));
		preview.SetText(wszText);
		gpreview.SendMsg(MTM_UPDATEEX, MTEXT_FLG_RTF, LPARAM(m_tempItem.formatRtf(wszText).c_str()));
	}

	void onSelChanged(CCtrlTreeView::TEventInfo *)
	{
		TVITEMEX tvi;
		tvi.hItem = m_tree.GetSelection();
		tvi.mask = TVIF_PARAM;
		m_tree.GetItem(&tvi);

		if (tvi.lParam == 0) {
			m_edit.Disable();
			preview.Disable();
			gpreview.Disable();
			btnDiscard.Disable();
			bthVarHelp.Disable();

			HTREEITEM hItem = m_tree.GetChild(tvi.hItem);
			if (hItem)
				m_tree.Expand(tvi.hItem, TVE_EXPAND);
			return;
		}

		m_edit.Enable();
		preview.Enable();
		gpreview.Enable();
		btnDiscard.Enable();
		bthVarHelp.Enable();

		if (m_curr != nullptr)
			replaceStrW(m_curr->tmpValue, m_edit.GetText());

		m_curr = (TemplateInfo *)tvi.lParam;

		if (m_curr->tmpValue)
			m_edit.SetText(m_curr->tmpValue);
		else if (m_curr->value)
			m_edit.SetText(m_curr->value);
		else
			m_edit.SetText(TranslateW(m_curr->defvalue));

		onChange_Edit();
	}
};

int OptionsInitialize(WPARAM wParam, LPARAM)
{
	OPTIONSDIALOGPAGE odp = {};
	odp.position = 100000000;
	odp.szGroup.a = LPGEN("History");
	odp.szTitle.a = LPGEN("NewStory");
	odp.flags = ODPF_BOLDGROUPS;

	odp.szTab.a = LPGEN("Templates");
	odp.pDialog = new CTemplateOptsDlg();
	g_plugin.addOptions(wParam, &odp);

	odp.szTab.a = LPGEN("Advanced");
	odp.pDialog = new CGeneralOptsDlg();
	g_plugin.addOptions(wParam, &odp);
	return 0;
}