<?php namespace HashOver;
// Copyright (C) 2018-2019 Jacob Barkdull
// This file is part of HashOver.
//
// HashOver is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// HashOver 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with HashOver.  If not, see <http://www.gnu.org/licenses/>.
// Generates an array of various settings information
function ui_array (Setup $setup, Locale $locale)
{
	// Theme names
	$themes = array ();
	// Themes directory
	$themes_directory = $setup->getAbsolutePath ('themes');
	// Get each theme directory name
	foreach (glob ($themes_directory . '/*', GLOB_ONLYDIR) as $directory) {
		$theme = basename ($directory);
		$themes[$theme] = $theme;
	}
	// Form fields options
	$field_options = array (
		'on'		=> $locale->text['enabled'],
		'required'	=> $locale->text['required'],
		'off'		=> $locale->text['disabled'],
	);
	// Return array of settings allowed to be changed
	return array (
		'general' => array (
			'language' => array (
				'type' => 'select',
				'value' => $setup->language,
				'options' => array (
					'en-us' => 'English',
					'pt-br' => 'Brazilian Portuguese',
					'da-dk' => 'Danish',
					'nl-nl' => 'Dutch',
					'eo-eo' => 'Esperanto',
					'fr-fr' => 'French',
					'de-de' => 'German',
					'el-el' => 'Greek',
					'ja-jp' => 'Japanese',
					'ko-kr' => 'Korean',
					'lt-lt' => 'Lithuanian',
					'fa-ir' => 'Persian',
					'pl-pl' => 'Polish',
					'ro-ro' => 'Romanian',
					'ru-ru' => 'Russian',
					'zh-cn' => 'Simplified Chinese',
					'es-es' => 'Spanish',
					'tr-tr' => 'Turkish'
				)
			),
			'theme' => array (
				'type' => 'select',
				'value' => $setup->theme,
				'options' => $themes
			),
			'default-sorting' => array (
				'type' => 'select',
				'value' => $setup->defaultSorting,
				'options' => array (
					'ascending'	=> $locale->text['sort-ascending'],
					'descending'	=> $locale->text['sort-descending'],
					'by-date'	=> $locale->text['sort-by-date'],
					'by-likes'	=> $locale->text['sort-by-likes'],
					'by-replies'	=> $locale->text['sort-by-replies'],
					'by-name'	=> $locale->text['sort-by-name'],
					'sort-threads' => array (
						'threaded-descending'	=> $locale->text['sort-descending'],
						'threaded-by-date'	=> $locale->text['sort-by-date'],
						'threaded-by-likes'	=> $locale->text['sort-by-likes'],
						'by-popularity'		=> $locale->text['sort-by-popularity'],
						'by-discussion'		=> $locale->text['sort-by-discussion'],
						'threaded-by-name'	=> $locale->text['sort-by-name']
					)
				)
			),
			'uses-markdown' => array (
				'type' => 'checkbox',
				'value' => $setup->usesMarkdown
			),
			'uses-ajax' => array (
				'type' => 'checkbox',
				'value' => $setup->usesAjax
			),
			'shows-reply-count' => array (
				'type' => 'checkbox',
				'value' => $setup->showsReplyCount
			),
			'allows-images' => array (
				'type' => 'checkbox',
				'value' => $setup->allowsImages
			),
			'allows-likes' => array (
				'type' => 'checkbox',
				'value' => $setup->allowsLikes
			),
			'allows-dislikes' => array (
				'type' => 'checkbox',
				'value' => $setup->allowsDislikes
			)
		),
		'moderation' => array (
			'uses-moderation' => array (
				'type' => 'checkbox',
				'value' => $setup->usesModeration
			),
			'pends-user-edits' => array (
				'type' => 'checkbox',
				'value' => $setup->pendsUserEdits
			)
		),
		'e-mail' => array (
			'mail-type' => array (
				'type' => 'select',
				'value' => $setup->mailType,
				'options' => array (
					'text' => 'Text',
					'html' => 'HTML'
				)
			),
			'mailer' => array (
				'type' => 'select',
				'value' => $setup->mailer,
				'options' => array (
					'sendmail' => 'Sendmail',
					'smtp' => 'SMTP'
				)
			),
			'subscribes-user' => array (
				'type' => 'checkbox',
				'value' => $setup->subscribesUser
			),
			'allows-user-replies' => array (
				'type' => 'checkbox',
				'value' => $setup->allowsUserReplies
			)
		),
		'cookies' => array (
			'sets-cookies' => array (
				'type' => 'checkbox',
				'value' => $setup->setsCookies
			),
			'cookie-expiration' => array (
				'type' => 'text',
				'documentation'=> 'https://www.php.net/manual/en/datetime.formats.relative.php',
				'value' => $setup->cookieExpiration
			),
			'secure-cookies' => array (
				'type' => 'checkbox',
				'value' => $setup->secureCookies
			)
		),
		'comment-collapsing' => array (
			'collapses-interface' => array (
				'type' => 'checkbox',
				'value' => $setup->collapsesInterface
			),
			'collapses-comments' => array (
				'type' => 'checkbox',
				'value' => $setup->collapsesComments
			),
			'collapse-limit' => array (
				'type' => 'number',
				'value' => $setup->collapseLimit
			)
		),
		'popular-comments' => array (
			'popularity-threshold' => array (
				'type' => 'number',
				'value' => $setup->popularityThreshold
			),
			'popularity-limit' => array (
				'type' => 'number',
				'value' => $setup->popularityLimit
			)
		),
		'spam-protection' => array (
			'spam-database' => array (
				'type' => 'select',
				'value' => $setup->spamDatabase,
				'options' => array (
					'remote' => 'StopForumSpam.com',
					'local' => 'Local CSV file'
				)
			),
			'spam-check-modes' => array (
				'type' => 'select',
				'value' => $setup->spamCheckModes,
				'options' => array (
					'both' => 'Both',
					'json' => 'JavaScript',
					'php' => 'PHP'
				)
			)
		),
		'avatars' => array (
			'icon-mode' => array (
				'type' => 'select',
				'value' => $setup->iconMode,
				'options' => array (
					'image' => 'Image',
					'count' => 'Count',
					'none' => 'None'
				)
			),
			'icon-size' => array (
				'type' => 'number',
				'value' => $setup->iconSize
			),
			'gravatar-default' => array (
				'type' => 'select',
				'value' => $setup->gravatarDefault,
				'options' => array (
					'custom' => 'Custom',
					'identicon' => 'Identicon',
					'monsterid' => 'Monsterid',
					'wavatar' => 'Wavatar',
					'retro' => 'Retro'
				)
			),
			'gravatar-force' => array (
				'type' => 'checkbox',
				'value' => $setup->gravatarForce
			)
		),
		'form-fields' => array (
			'form-position' => array (
				'type' => 'select',
				'value' => $setup->formPosition,
				'options' => array (
					'top' => 'Top',
					'bottom' => 'Bottom'
				)
			),
			'name-field' => array (
				'type' => 'select',
				'value' => $setup->nameField,
				'options' => $field_options
			),
			'password-field' => array (
				'type' => 'select',
				'value' => $setup->passwordField,
				'options' => $field_options
			),
			'email-field' => array (
				'type' => 'select',
				'value' => $setup->emailField,
				'options' => $field_options
			),
			'website-field' => array (
				'type' => 'select',
				'value' => $setup->websiteField,
				'options' => $field_options
			),
			'displays-title' => array (
				'type' => 'checkbox',
				'value' => $setup->displaysTitle
			),
			'uses-cancel-buttons' => array (
				'type' => 'checkbox',
				'value' => $setup->usesCancelButtons
			),
			'uses-labels' => array (
				'type' => 'checkbox',
				'value' => $setup->usesLabels
			)
		),
		'date-time' => array (
			'date-pattern' => array (
				'documentation' => 'http://userguide.icu-project.org/formatparse/datetime',
				'type' => 'text',
				'value' => $setup->datePattern
			),
			'time-pattern' => array (
				'type' => 'text',
				'value' => $setup->timePattern
			),
			'server-timezone' => array (
				'documentation' => 'https://php.net/manual/en/timezones.php',
				'type' => 'text',
				'value' => $setup->serverTimezone
			),
			'uses-user-timezone' => array (
				'type' => 'checkbox',
				'value' => $setup->usesUserTimezone
			),
			'uses-short-dates' => array (
				'type' => 'checkbox',
				'value' => $setup->usesShortDates
			)
		),
		'login' => array (
			'login-method' => array (
				'type' => 'select',
				'value' => $setup->loginMethod,
				'options' => array (
					'DefaultLogin' => 'Cookies Login',
					'SessionLogin' => 'Session Login'
				)
			),
			'allows-login' => array (
				'type' => 'checkbox',
				'value' => $setup->allowsLogin
			),
			'uses-auto-login' => array (
				'type' => 'checkbox',
				'value' => $setup->usesAutoLogin
			)
		),
		'technical' => array (
			'data-format' => array (
				'type' => 'select',
				'value' => $setup->dataFormat,
				'options' => array (
					'xml' => 'XML',
					'json' => 'JSON',
					'sql' => 'SQL'
				)
			),
			'default-name' => array (
				'type' => 'text',
				'value' => $setup->defaultName
			),
			'reply-mode' => array (
				'type' => 'select',
				'value' => $setup->replyMode,
				'options' => array (
					'thread' => 'Threaded',
					'stream' => 'Stream'
				)
			),
			'stream-depth' => array (
				'type' => 'number',
				'value' => $setup->streamDepth
			),
			'image-format' => array (
				'type' => 'select',
				'value' => $setup->imageFormat,
				'options' => array (
					'png' => 'PNG',
					'svg' => 'SVG'
				)
			),
			'appends-css' => array (
				'type' => 'checkbox',
				'value' => $setup->appendsCss
			),
			'appends-rss' => array (
				'type' => 'checkbox',
				'value' => $setup->appendsRss
			),
			'counts-deletions' => array (
				'type' => 'checkbox',
				'value' => $setup->countsDeletions
			),
			'local-metadata' => array (
				'type' => 'checkbox',
				'value' => $setup->localMetadata
			),
			'stores-ip-address' => array (
				'type' => 'checkbox',
				'value' => $setup->storesIpAddress
			)
		),
		'JavaScript' => array (
			'minifies-javascript' => array (
				'type' => 'checkbox',
				'value' => $setup->minifiesJavascript
			),
			'minify-level' => array (
				'type' => 'select',
				'cast' => 'number',
				'value' => $setup->minifyLevel,
				'options' => array (
					1 => 'Basic (removes code comments)',
					2 => 'Low (removes whitespace + Basic)',
					3 => 'Medium (removes newlines + Low)',
					4 => 'High (removes extra bits + Medium)'
				)
			)
		)
	);
}
// Creates a select element with setting options
function create_select ($hashover, $name, array $setting)
{
	// Create wrapper element for dropdown menu
	$element = new HTMLTag ('span', array (
		'class' => 'select-wrapper'
	));
	// Create dropdown menu
	$select = new HTMLTag ('select', array (
		'id' => $name,
		'name' => $name,
		'size' => 1
	));
	// Run through setting options
	foreach ($setting['options'] as $value => $data) {
		// Check if the current option is an array
		if (is_array ($data)) {
			// If so, add an option group spacer to menu
			$select->appendChild (new HTMLTag ('optgroup', array (
				'label' => ' '
			)));
			// Create an option group with localized label
			$optgroup = new HTMLTag ('optgroup', array (
				'label' => $hashover->locale->text[$value]
			));
			// Run through each optgroup option
			foreach ($data as $opt_value => $opt_text) {
				// Create setting option
				$option = new HTMLTag ('option', array (
					'value' => $opt_value,
					'innerHTML' => $opt_text
				), false);
				// Select proper option
				if ($opt_value === $setting['value']) {
					$option->createAttribute ('selected', 'true');
				}
				// Append option to optgroup
				$optgroup->appendChild ($option);
			}
			// And append optgroup to menu
			$select->appendChild ($optgroup);
		} else {
			// If not, create setting option
			$option = new HTMLTag ('option', array (
				'value' => $value,
				'innerHTML' => $data
			), false);
			// Select proper option
			if ($value === $setting['value']) {
				$option->createAttribute ('selected', 'true');
			}
			// Append option to menu
			$select->appendChild ($option);
		}
	}
	// Append dropdown menu to wrapper element
	$element->appendChild ($select);
	return $element;
}
// Creates a paragraph element for a setting value
function create_paragraph ($hashover, $name, array $setting)
{
	// Create setting description and value paragraph
	$paragraph = new HTMLTag ('p');
	// Setting description locale string
	$text = $hashover->locale->text['setting-' . $name];
	// Create description label
	$label = new HTMLTag ('label', array (
		'for' => $name,
		'innerHTML' => $text
	), false);
	// Get documentation locale string
	$docs = $hashover->locale->text['documentation'];
	// Create documentation link
	$docs_link = new HTMLTag ('a', array (
		'class' => 'docs-link',
		'href' => '../docs/en-us/settings/#' . $name,
		'target' => '_blank',
		'title' => $docs,
		'innerHTML' => '?'
	), false);
	// Handle specific setting types
	switch ($setting['type']) {
		// Create checkbox for enabling/disabling the setting
		case 'checkbox': {
			// Create checkbox type input element
			$element = new HTMLTag ('input', array (
				'id' => $name,
				'type' => 'checkbox',
				'name' => $name
			), false, true);
			// Set check based on current setting
			if ($setting['value'] !== false) {
				$element->createAttribute ('checked', 'true');
			}
			break;
		}
		// Create text/number box for entering the setting value
		case 'number' : case 'text': {
			// Add class to make label a block element
			$label->createAttribute ('class', 'block');
			// And create number or text type input element
			$element = new HTMLTag ('input', array (
				'id' => $name,
				'type' => $setting['type'],
				'name' => $name,
				'value' => $setting['value'],
				'size' => ($setting['type'] === 'text') ? '25' : '10'
			), false, true);
			break;
		}
		// Create dropdown menu for selecting the setting value
		case 'select': {
			// Add class to make label a block element
			$label->createAttribute ('class', 'block');
			// Create select element
			$element = create_select ($hashover, $name, $setting);
			break;
		}
	}
	// Check if setting is a checkbox
	if ($setting['type'] === 'checkbox') {
		// If so, append setting value element to paragraph
		$paragraph->appendChild ($element);
		// Then append label element to paragraph
		$paragraph->appendChild ($label);
		// Append documentation link to description and value paragraph
		$paragraph->appendChild ($docs_link);
	} else {
		// If not, append documentation link to description label
		$label->appendChild ($docs_link);
		// Append label element to paragraph
		$paragraph->appendChild ($label);
		// Then append setting value element to paragraph
		$paragraph->appendChild ($element);
	}
	// And return paragraph element
	return $paragraph;
}
try {
	// Do some standard HashOver setup work
	require (realpath ('../../backend/standard-setup.php'));
	// View setup
	require (realpath ('../view-setup.php'));
	// Get array of UI elements to create
	$ui = ui_array ($hashover->setup, $hashover->locale);
	// Check if the form has been submitted
	if (isset ($_POST['save'])) {
		// Settings JSON file path
		$settings_file = $hashover->setup->getAbsolutePath ('config/settings.json');
		// Read JSON settings file
		$json = $data_files->readJSON ($settings_file);
		// Existing JSON settings or an empty array
		$settings = ($json !== false) ? $json : array ();
		// Run through configurable settings
		foreach ($ui as $items) {
			// Run through each settings category
			foreach ($items as $name => $setting) {
				// Use specified type or optional cast
				$type = !empty ($setting['cast']) ? 'cast' : 'type';
				// Handle specific setting types
				switch ($setting[$type]) {
					// Set value to boolean based on POST data
					case 'checkbox': {
						$settings[$name] = isset ($_POST[$name]);
						break;
					}
					// Cast number values to integers
					case 'number': {
						$settings[$name] = (int)($_POST[$name]);
						break;
					}
					// All other values are strings
					default: {
						// Check if setting has a value
						if (!empty ($_POST[$name])) {
							// If so, cast it to string before setting it
							$settings[$name] = (string)($_POST[$name]);
						} else {
							// If not, remove the setting entirely
							unset ($settings[$name]);
						}
						break;
					}
				}
			}
		}
		// Check if the user login is admin
		if ($hashover->login->verifyAdmin () === true) {
			// If so, attempt to save the settings
			$saved = $data_files->saveJSON ($settings_file, $settings);
			// If saved successfully, redirect with success indicator
			if ($saved === true) {
				redirect ('./?status=success');
			}
		}
		// Otherwise, redirect with failure indicator
		redirect ('./?status=failure');
	}
	// Otherwise, create settings div
	$div = new HTMLTag ('div', array (
		'id' => 'settings'
	));
	// Create settings divs
	foreach ($ui as $locale => $settings) {
		// Replace key with locale string if one exists
		if (!empty ($hashover->locale->text[$locale])) {
			$locale = $hashover->locale->text[$locale];
		}
		// Append settings category text to settings div
		$div->appendChild (new HTMLTag ('p', array (
			'class' => 'settings-category',
			'innerHTML' => $locale
		), false));
		// Create settings items element
		$items = new HTMLTag ('div', array (
			'class' => 'settings'
		));
		// Append each settings category items to div
		foreach ($settings as $name => $setting) {
			$items->appendChild (create_paragraph ($hashover, $name, $setting));
		}
		// Append settings items element to div
		$div->appendChild ($items);
	}
	// Template data
	$template = array (
		'title'		=> $hashover->locale->text['settings'],
		'sub-title'	=> $hashover->locale->text['settings-sub'],
		'settings'	=> $div->asHTML ("\t"),
		'save-button'	=> $hashover->locale->text['save']
	);
	// Load and parse HTML template
	echo parse_templates ('admin', 'settings.html', $template, $hashover);
} catch (\Exception $error) {
	echo Misc::displayException ($error);
}