/*
 * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
 * Copyright 2009, Pier Luigi Fiorini.
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *		Pier Luigi Fiorini, pierluigi.fiorini@gmail.com
 *		Brian Hill, supernova@tycho.email
 */
 
#include "PrefletWin.h"
 
#include <Alert.h>
#include <Application.h>
#include <Button.h>
#include <Catalog.h>
#include <FindDirectory.h>
#include <Notification.h>
#include <Path.h>
#include <SeparatorView.h>
 
#include <notification/Notifications.h>
 
#include "NotificationsConstants.h"
#include "PrefletView.h"
 
 
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "PrefletWin"
 
const BString kSampleMessageID("NotificationsSample");
 
 
PrefletWin::PrefletWin()
	:
	BWindow(BRect(0, 0, 160 + 20 * be_plain_font->Size(), 300),
		B_TRANSLATE_SYSTEM_NAME("Notifications"),
		B_TITLED_WINDOW, B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS
		| B_AUTO_UPDATE_SIZE_LIMITS)
{
	// Preflet container view
	fMainView = new PrefletView(this);
	fMainView->SetBorder(B_NO_BORDER);
	fMainView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED));
 
	// Defaults button
	fDefaults = new BButton("defaults", B_TRANSLATE("Defaults"),
		new BMessage(kDefaults));
	fDefaults->SetEnabled(false);
 
	// Revert button
	fRevert = new BButton("revert", B_TRANSLATE("Revert"),
		new BMessage(kRevert));
	fRevert->SetEnabled(false);
 
	// Build the layout
	fButtonsView = new BGroupView();
	BLayoutBuilder::Group<>(fButtonsView, B_VERTICAL, 0)
		.AddGroup(B_HORIZONTAL)
			.Add(fDefaults)
			.Add(fRevert)
			.AddGlue()
			.SetInsets(B_USE_WINDOW_SPACING, 0, B_USE_WINDOW_SPACING,
				B_USE_WINDOW_SPACING)
		.End();
	fButtonsLayout = fButtonsView->GroupLayout();
	
	BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
		.SetInsets(0, B_USE_DEFAULT_SPACING, 0, 0)
		.Add(fMainView)
		.Add(fButtonsView)
	.End();
	fMainView->SetExplicitMinSize(BSize(Frame().Width(), B_SIZE_UNSET));
 
	ReloadSettings();
 
	// Center this window on screen and show it
	CenterOnScreen();
	Show();
}
 
 
void
PrefletWin::MessageReceived(BMessage* msg)
{
	switch (msg->what) {
		case kApply:
		case kApplyWithExample:
		{
			BPath path;
 
			status_t ret = B_OK;
			ret = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
			if (ret != B_OK)
				return;
 
			path.Append(kSettingsFile);
 
			BMessage settingsStore;
			int32 count = fMainView->CountTabs();
			for (int32 i = 0; i < count; i++) {
				SettingsPane* pane =
					dynamic_cast<SettingsPane*>(fMainView->PageAt(i));
				if (pane) {
					if (pane->Save(settingsStore) == B_OK) {
						fDefaults->SetEnabled(_DefaultsPossible());
						fRevert->SetEnabled(_RevertPossible());
					} else
						break;
				}
			}
 
			// Save settings file
			BFile file(path.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
			ret = settingsStore.Flatten(&file);
			if (ret != B_OK) {
				BAlert* alert = new BAlert("",
					B_TRANSLATE("An error occurred saving the preferences.\n"
						"It's possible you are running out of disk space."),
					B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_AS_USUAL,
					B_STOP_ALERT);
				alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
				(void)alert->Go();
			}
			file.Unset();
 
			if (msg->what == kApplyWithExample)
				_SendExampleNotification();
 
			break;
		}
		case kDefaults:
			fDefaults->SetEnabled(false);
			_Defaults();
			PostMessage(kApply);
			break;
		case kRevert:
			fRevert->SetEnabled(false);
			_Revert();
			PostMessage(kApply);
			break;
		case kShowButtons: {
			bool show = msg->GetBool(kShowButtonsKey, true);
			fButtonsLayout->SetVisible(show);
			break;
		}
		default:
			BWindow::MessageReceived(msg);
	}
}
 
 
bool
PrefletWin::QuitRequested()
{
	be_app_messenger.SendMessage(B_QUIT_REQUESTED);
	return true;
}
 
 
void
PrefletWin::SettingChanged(bool showExample)
{
	if (showExample)
		PostMessage(kApplyWithExample);
	else
		PostMessage(kApply);
}
 
 
void
PrefletWin::ReloadSettings()
{
	BPath path;
 
	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
		return;
 
	// FIXME don't load this again here, share with other tabs!
	path.Append(kSettingsFile);
 
	BMessage settings;
	BFile file(path.Path(), B_READ_ONLY);
	settings.Unflatten(&file);
 
	int32 count = fMainView->CountTabs();
	for (int32 i = 0; i < count; i++) {
		SettingsPane* pane =
			dynamic_cast<SettingsPane*>(fMainView->PageAt(i));
		if (pane)
			pane->Load(settings);
	}
	fDefaults->SetEnabled(_DefaultsPossible());
}
 
 
status_t
PrefletWin::_Revert()
{
	int32 count = fMainView->CountTabs();
	for (int32 i = 0; i < count; i++) {
		SettingsPane* pane =
			dynamic_cast<SettingsPane*>(fMainView->PageAt(i));
		if (pane)
			pane->Revert();
	}
	return B_OK;
}
 
 
bool
PrefletWin::_RevertPossible()
{
	int32 count = fMainView->CountTabs();
	for (int32 i = 0; i < count; i++) {
		SettingsPane* pane =
			dynamic_cast<SettingsPane*>(fMainView->PageAt(i));
		if (pane && pane->RevertPossible())
			return true;
	}
	return false;
}
 
 
status_t
PrefletWin::_Defaults()
{
	int32 count = fMainView->CountTabs();
	for (int32 i = 0; i < count; i++) {
		SettingsPane* pane =
			dynamic_cast<SettingsPane*>(fMainView->PageAt(i));
		if (pane)
			pane->Defaults();
	}
	return B_OK;
}
 
 
bool
PrefletWin::_DefaultsPossible()
{
	int32 count = fMainView->CountTabs();
	for (int32 i = 0; i < count; i++) {
		SettingsPane* pane =
			dynamic_cast<SettingsPane*>(fMainView->PageAt(i));
		if (pane && pane->DefaultsPossible())
			return true;
	}
	return false;
}
 
 
void
PrefletWin::_SendExampleNotification()
{
	BNotification notification(B_INFORMATION_NOTIFICATION);
	notification.SetMessageID(kSampleMessageID);
	notification.SetGroup(B_TRANSLATE("Notifications"));
	notification.SetTitle(B_TRANSLATE("Notifications preflet sample"));
	notification.SetContent(B_TRANSLATE("This is a test notification message"));
	notification.Send();
}

V773 Visibility scope of the 'alert' pointer was exited without releasing the memory. A memory leak is possible.