<?php
/*****************************************************************************
 * FormView.php
 * Contains the form template.
 *
 * Kabuki CMS (C) 2013-2023, Aaron van Geffen
 *****************************************************************************/

class FormView extends SubTemplate
{
	private $form;
	private array $data;
	private array $missing;
	private $title;

	public function __construct(Form $form, $title = '')
	{
		$this->form = $form;
		$this->title = $title;
	}

	protected function html_content($exclude = [], $include = [])
	{
		if (!empty($this->title))
			echo '
			<h1>', $this->title, '</h1>';

		foreach ($this->_subtemplates as $template)
			$template->html_main();

		echo '
			<form action="', $this->form->request_url, '" method="', $this->form->request_method, '" enctype="multipart/form-data">';

		if (isset($this->form->content_above))
			echo $this->form->content_above;

		$this->missing = $this->form->getMissing();
		$this->data = $this->form->getData();

		foreach ($this->form->getFields() as $field_id => $field)
		{
			// Either we have a blacklist
			if (!empty($exclude) && in_array($field_id, $exclude))
				continue;
			// ... or a whitelist
			elseif (!empty($include) && !in_array($field_id, $include))
				continue;
			// ... or neither (ha)

			$this->renderField($field_id, $field);
		}

		echo '
				<input type="hidden" name="', Session::getSessionTokenKey(), '" value="', Session::getSessionToken(), '">
				<div class="form-group">
					<div class="offset-sm-2 col-sm-10">
						<button type="submit" name="submit" class="btn btn-primary">', $this->form->getSubmitButtonCaption(), '</button>';

		if (isset($this->form->content_below))
			echo '
						', $this->form->content_below;

		echo '
					</div>
				</div>
			</form>';
	}

	protected function renderField($field_id, array $field)
	{
		if (isset($field['before_html']))
			echo '
				', $field['before_html'];

		echo '
				<div class="row mb-2">';

		if (isset($field['before']))
			echo $field['before'];

		if ($field['type'] !== 'checkbox')
			if (isset($field['label']))
				echo '
					<label class="col-sm-2 col-form-label" for="', $field_id, '"', in_array($field_id, $this->missing) ? ' style="color: red"' : '', '>', $field['label'], ':</label>
					<div class="', isset($field['class']) ? $field['class'] : 'col-sm-6', '">';
			else
				echo '
					<div class="offset-sm-2 ', isset($field['class']) ? $field['class'] : 'col-sm-6', '">';

		switch ($field['type'])
		{
			case 'select':
				$this->renderSelect($field_id, $field);
				break;

			case 'radio':
				$this->renderRadio($field_id, $field);
				break;

			case 'checkbox':
				$this->renderCheckbox($field_id, $field);
				break;

			case 'textarea':
				$this->renderTextArea($field_id, $field);
				break;

			case 'color':
				$this->renderColor($field_id, $field);
				break;

			case 'numeric':
				$this->renderNumeric($field_id, $field);
				break;

			case 'file':
				$this->renderFile($field_id, $field);
				break;

			case 'captcha':
				$this->renderCaptcha($field_id, $field);
				break;

			case 'text':
			case 'password':
			default:
				$this->renderText($field_id, $field);
		}

		if (isset($field['after']))
			echo ' ', $field['after'];

		if ($field['type'] !== 'checkbox')
			echo '
					</div>';

		echo '
				</div>';
	}

	private function renderCaptcha($field_id, array $field)
	{
		echo '
						<div class="g-recaptcha" data-sitekey="', RECAPTCHA_API_KEY, '"></div>
						<script src="https://www.google.com/recaptcha/api.js"></script>';
	}

	private function renderCheckbox($field_id, array $field)
	{
		echo '
					<div class="offset-sm-2 col-sm-10">
						<div class="form-check">
							<input class="form-check-input" type="checkbox"', $this->data[$field_id] ? ' checked' : '', !empty($field['disabled']) ? ' disabled' : '', ' name="', $field_id, '" id="check-', $field_id, '">
							<label class="form-check-label" for="check-', $field_id, '">
								', $field['label'], '
							</label>
						</div>
					</div>';
	}

	private function renderColor($field_id, array $field)
	{
		echo '
						<input class="form-control" type="color" name="', $field_id, '" id="', $field_id, '" value="', htmlspecialchars($this->data[$field_id]), '"', !empty($field['disabled']) ? ' disabled' : '', '>';
	}

	private function renderFile($field_id, array $field)
	{
		if (!empty($this->data[$field_id]))
			echo 'Currently using asset <tt>', $this->data[$field_id], '</tt>. Upload to overwrite.<br>';

		echo '
						<input class="form-control" type="file" name="', $field_id, '" id="', $field_id, '"', !empty($field['disabled']) ? ' disabled' : '', '>';
	}

	private function renderNumeric($field_id, array $field)
	{
		echo '
						<input class="form-control" type="number"',
							isset($field['step']) ? ' step="' . $field['step'] . '"' : '',
							' min="', isset($field['min_value']) ? $field['min_value'] : '0', '"',
							' max="', isset($field['max_value']) ? $field['max_value'] : '9999', '"',
							' name="', $field_id, '" id="', $field_id, '"',
							isset($field['size']) ? ' size="' . $field['size'] . '"' : '',
							isset($field['maxlength']) ? ' maxlength="' . $field['maxlength'] . '"' : '',
							' value="', htmlspecialchars($this->data[$field_id]), '"',
							!empty($field['disabled']) ? ' disabled' : '', '>';
	}

	private function renderRadio($field_id, array $field)
	{
		foreach ($field['options'] as $value => $option)
			echo '
						<div class="form-check">
							<input class="form-check-input" type="radio" name="', $field_id, '" id="radio-', $field_id, '-', $value, '" value="', $value, '"', $this->data[$field_id] == $value ? ' checked' : '', !empty($field['disabled']) ? ' disabled' : '', '>
							<label class="form-check-label" for="radio-', $field_id, '-', $value, '">
								', htmlspecialchars($option), '
							</label>
						</div>';
	}

	private function renderSelect($field_id, array $field)
	{
		echo '
						<select class="form-select" name="', $field_id, !empty($field['multiple']) ? '[]' : '',
					'" id="', $field_id, '"',
					!empty($field['disabled']) ? ' disabled' : '',
					!empty($field['multiple']) ? ' multiple' : '',
					!empty($field['size']) ? ' size="' . $field['size'] . '"' : '',
					'>';

		if (isset($field['placeholder']))
			echo '
							<option value="">', $field['placeholder'], '</option>';

		foreach ($field['options'] as $key => $value)
		{
			if (is_array($value))
			{
				assert(empty($field['multiple']));
				$this->renderSelectOptionGroup($field_id, $key, $value);
			}
			else
				$this->renderSelectOption($field_id, $value, $key, !empty($field['multiple']));
		}

		echo '
						</select>';
	}

	private function renderSelectOption($field_id, $label, $value, $multiple = false)
	{
		echo '
							<option value="', $value, '"',
							!$multiple && $this->data[$field_id] == $value ? ' selected' : '',
							$multiple && in_array($value, $this->data[$field_id]) ? ' selected' : '',
							'>', htmlspecialchars($label), '</option>';
	}

	private function renderSelectOptionGroup($field_id, $label, $options)
	{
		echo '
							<optgroup label="', $label, '">';

		foreach ($options as $value => $option)
			$this->renderSelectOption($field_id, $option, $value);

		echo '
							</optgroup>';
	}

	private function renderText($field_id, array $field)
	{
		echo '
						<input class="form-control" ',
						'type="', $field['type'], '" ',
						'name="', $field_id, '" ',
						'id="', $field_id, '"',
						isset($field['size']) ? ' size="' . $field['size'] . '"' : '',
						isset($field['maxlength']) ? ' maxlength="' . $field['maxlength'] . '"' : '',
						isset($this->data[$field_id]) ? ' value="' . htmlspecialchars($this->data[$field_id]) . '"' : '',
						isset($field['placeholder']) ? ' placeholder="' . $field['placeholder'] . '"' : '',
						!empty($field['disabled']) ? ' disabled' : '',
						isset($field['trigger']) ? ' class="trigger-' . $field['trigger'] . '"' : '',
						'>';
	}

	private function renderTextArea($field_id, array $field)
	{
		echo '
						<textarea class="form-control' .
							'" name="', $field_id,
							'" id="', $field_id,
							'" cols="', isset($field['columns']) ? $field['columns'] : 40,
							'" rows="', isset($field['rows']) ? $field['rows'] : 4, '"',
							isset($field['placeholder']) ? ' placeholder="' . $field['placeholder'] . '"' : '',
							'"', !empty($field['disabled']) ? ' disabled' : '',
							'>', $this->data[$field_id], '</textarea>';
	}
}