<?php

require __DIR__ . '/components.php';

class FormEdit_Model extends Database_model {

	private $user_settings;
	private $form_id;
	private $DATA;
	private $changed;
	private $DEFS;
	public $x_data;
	
	function __construct() {
		parent::__construct();
		$this->changed = FALSE;
		$this->DEFS = [
			formEditBase::Create($this, 	'string',	'name',		'Name'),
			formEditBase::Create($this, 	'email',	'email',	'Email'),
			formEditBase::Create($this, 	'tel', 	'phone',	'Phone'),
			formEditBase::Create($this, 	'string', 	'state',	'State'),
			formEditBase::Create($this, 	'string', 	'zip',		'Zip/Postcode'),
			formEditBase::Create($this, 	'text', 	'message',	'Message'),
			formEditBase::Create($this, 	'submit', 	'button',	'Submit Request'),
		];
	}

	public function FormId() {
		if (func_num_args()) {
			$this->form_id = func_get_arg(0);
			if ($this->form_id == 'new') {
				$this->form_id = substr(md5('asqflasd:' . time()), 4, 8);
			}
			$this->Load();
			return $this;
		}
		return $this->form_id;
	}
	
	protected function Load() {
		$data = $this->Query('select cfg_hash,cfg_text from config')
					->Where('cfg_hash = %s', 'formedit:' . $this->form_id)
					->First();
		$this->DbErr();
		if (is_null($data) || $data->empty()) {
			$this->DATA = [];
		} else {
			$this->DATA = unserialize($data->cfg_text);
		}
		$this->changed = FALSE;
	}

	public function Title() {
		if (func_num_args()) {
			$this->DATA['title'] = func_get_arg(0);
			return $this;
		}
		return $this->DATA['title'] ?? '(untitled)';
	}
	public function Redirect() {
		if (func_num_args()) {
			$this->DATA['redirect'] = func_get_arg(0);
			return $this;
		}
		return $this->DATA['redirect'] ?? '';
	}
	public function Focus() {
		if (func_num_args()) {
			$this->DATA['focus'] = func_get_arg(0) ? 1 : 0;
			return $this;
		}
		return $this->DATA['focus'];
	}
	public function Fields() {
		if (func_num_args()) {
			$this->DATA['fields'] = func_get_arg(0);
			if (is_string($this->DATA['fields'])) {
				$this->DATA['fields'] = explode(';', $this->DATA['fields']);
			}
			return $this;
		}
		return $this->DATA['fields'] ?? [];
	}
	public function Sender() {
		if (func_num_args()) {
			$this->DATA['sender'] = func_get_arg(0);
			return $this;
		}
		$sender = $this->DATA['sender'] ?? '';
		if ($sender == '') {		// default to system email address
			$settings = $this->SettingGet('config.module_info', NULL);
			$sender = $settings['replyto'] ?? '';
		}
		return $sender;
	}
	public function Recipient() {
		if (func_num_args()) {
			$this->DATA['recipient'] = func_get_arg(0);
			return $this;
		}
		return $this->DATA['recipient'] ?? '';
	}
	public function Subject() {
		if (func_num_args()) {
			$this->DATA['subject'] = func_get_arg(0);
			return $this;
		}
		$subject = $this->DATA['subject'] ?? '';
		if ($subject == '') $subject = "Form response — {$this->DATA['title']}";
		return $subject;
		
	}
	public function Body() {
		if (func_num_args()) {
			$this->DATA['body'] = func_get_arg(0);
			return $this;
		}
		return $this->DATA['body'] ?? '';
	}


	public function SaveRecord() {
		$this->TableName('config')
			->InsertOrUpdate([
				'cfg_hash' => 'formedit:' . $this->form_id,
			], [
				'cfg_text' => serialize($this->DATA),
			]);
		$this->changed = TRUE;
		return $this;
	}

	public function CustomFields($rep) {
		
		$rep->pagesize(25)
			->AutoWidth(FALSE);

		$col = $rep->AddColumn();
		$col->name('id')
			->caption('ID')
			->Width(80)
			->Source(function($item) {
				[ $category, $id ] = explode(':', $item->cfg_hash);
				return $id;
			});

		$col = $rep->AddColumn();
		$col->name('title')
			->caption('Title')
			->Source(function($item) {
				$payload = unserialize($item->cfg_text);
				return $payload['title'] ?? '(untitled)';
			})
			->Render(function($value, $item) {
				[ $category, $id ] = explode(':', $item->cfg_hash);
				$auth = hook_execute('nonce.create', FALSE, 'carousel', $id, 1800);
				$dvalue = htmlspecialchars($value);
				return "<a href=\"/admin/form/{$id}?auth={$auth}\">$dvalue</a>";
			});

	}
	
	public function formsList($rep) {
		$data = $rep->Query('select cfg_hash,cfg_text from config')
					->Where('cfg_hash like %s', 'formedit:%')
					->Execute();
		return array('data' => $data);
	}

	public function AsDraggableObject($item) {
		$fieldname = $item['name'];
		$caption = $item['caption'];
		$dcaption = htmlspecialchars($caption);
		return <<<BLOCK
<div class="formwizard_item" id="fe_{$fieldname}" data-name="{$fieldname}">{$dcaption}<div class="formwizard_itemedit" onclick="formwizard_remove('{$fieldname}')"></div></div>

BLOCK;
	}
	
	public function fieldsAvailable() {
		$fields = $this->DATA['fields'] ?? [];
		$output = '';
		foreach($this->DEFS as $definition) {
			if (!in_array($definition->Name(), $fields)) {
				$output .= $definition->AsDraggableObject();
			}
		}
		return $output;
	}
	
	protected function getDefinitions() {
		$lookup = [];
		foreach($this->DEFS as $definition) {
			$name = $definition->Name();
			$lookup[$name] = $definition;
		}
		return $lookup;
	}
	
	public function fieldsUsed() {
		$lookup = $this->getDefinitions();
		$fields = $this->DATA['fields'] ?? [];
		$output = '';
		foreach($fields as $fieldname) {
			if (isset($lookup[$fieldname])) {
				$def = $lookup[$fieldname];
				$output .= $def->AsDraggableObject();
			}
		}
		return $output;
	}
	
	public function AsPreview($preview = 1) {
		$lookup = $this->getDefinitions();
		$data = [ 
			'fieldlist' => [],
			'preview'	=> $preview,
		];
		$this->x_data = $data;		// configuration options

		// get the fields, and current defaults
		$fields = $this->DATA['fields'] ?? [];
		foreach($fields as $fieldname) {
			if (isset($lookup[$fieldname])) {
				$data['fieldlist'][] = $lookup[$fieldname]->AsJson();
				$data[$fieldname] = $this->DATA['default'][$fieldname] ?? '';		// supply a default value
			}
		}
		// load the view
		// use handlebars to create the html
		$callback = $this->controller->LoadHandlebarsView('FormEdit_View::handlebars_template');
		$output = $callback($data);
		return $output;
	}
	
	public function AsHTML() {
		$form = $this->AsPreview(0);
		$auth = hook_execute('nonce.create', FALSE, 'response', $this->form_id, 1800);
		return <<<BLOCK
<form class="frm json" method="POST" action="/~/formEdit/submission" style="width:650px">
<input type="hidden" name="auth" value="{$auth}">
{$form}
</form>
BLOCK;
	}
	
	public function setDefaultValues($post) {
		$lookup = $this->getDefinitions();
		$this->DATA['default'] = [];
		foreach($lookup as $key => $definition) {
			$name = $definition->Name();
			$value = trim($post[$name] ?? '');
			if ($value != '') {
				$this->DATA['default'][$name] = $value;
			}
		}
		return $this;
	}
	
	public function processSubmission($post, $ip_address, $language) {
		// check required fields

		// get params
		$payload = [];
		$lookup = $this->getDefinitions();
		$fields = $this->DATA['fields'] ?? [];
		foreach($fields as $fieldname) {
			if (isset($lookup[$fieldname])) {
				$payload[$fieldname] = $post[$fieldname] ?? '';
			}
		}

		// 
		$country = '??';
		$info = hook_execute('geoip.lookup', FALSE, $ip_address);
		if ($info !== FALSE) {
			$country = $info['country'] ?? '--';
		}

		// spam check
		$param = new StdClass;
		$param->post = $post;
		$param->lookup = $lookup;
		$param->isSpam = FALSE;
		$param->score = 0;
		$param = hook_execute('form.checkspam', $param);

		// save in database
		$node = new database_record($this);
		$node->TableName('form_response');
		$node->fr_formid = $this->form_id;
		$node->fr_timestamp = time();	// expiry time?
		$node->fr_data = json_encode($payload, JSON_UNESCAPED_SLASHES);
		$node->fr_ip = $ip_address;
		$node->fr_country = $country;
		$node->fr_lang = $language;
		$node->fr_score = $param->score;
		$node->SaveRecord();

		if ($param->isSpam) {
			return $this->DATA['redirect'] ?? FALSE;
		}

		$recipient = $this->Recipient();		// TO DO: break into individ addresses?
		if (!empty($recipient)) {
			$payload['ipaddress'] = $ip_address;
			$payload['countrycode'] = $country;
			$payload['language'] = $language;
			$subject = $this->Subject();
			$template = $this->Body();
			
			$callback = $this->controller->LoadHandlebars($template);
			$body = $callback($payload);
			
			$m = new \mailobject();
			$m	->Body($body)
				->Subject($subject)
				->From($this->Sender())
				->To($recipient);
			if (!empty($payload['email'])) {
				if (empty($payload['name'])) {
					$m->ReplyTo($payload['email']);
				} else {
					$m->ReplyTo($payload['email'], $payload['name']);
				}
			}
			$res = $m->Send();
//			error_log('formedit: ' . json_encode($res));
		}
		
		// return response
		return $this->DATA['redirect'] ?? FALSE;
	}

}