<?php

namespace modules\config;

class main extends \moduleMain {
	use traits {
			traits::__construct as __ConstructConfig;
		}
	use \modules\input\traits {
			\modules\input\traits::__construct as __ConstructInput;
		}

	private $salt;
	//private $settings;

	public function __construct() {
		parent::__construct(__DIR__);
		$this->__ConstructInput();
		$this->__ConstructConfig();
	}

	public function Activate() {
		$this->settings = $this->SettingGet('config.module_info', NULL);
		$this->salt = isset($this->settings['key']) ? $this->settings['secret'] : LOCK_FILE;	// must have a private key before a secret hash
		if (method_exists($GLOBALS['loader'], 'Salt')) {
			$GLOBALS['loader']->Salt($this->salt);
		} else {
			$GLOBALS['loader']->SetSalt($this->salt);
		}
		
	// install hooks
		hook_add('global.load', [$this, '__global_load']);
		hook_add('uri', [$this, '__check'], 1);
		hook_add('group.enum', [$this, '__setupgroups']);
		
		hook_add('nonce.create', [$this, '__nonce_create']);
		hook_add('nonce.verify', [$this, '__nonce_verify']);
		hook_add('nonce.public', [$this, '__public_create']);		// create something that can be decrypted by the public key
		hook_add('config.get', [$this, '__getconfigitem'], 10);		// filesystem handler for 'config' settings. must load before db handler
		hook_add('config.set', [$this, '__setconfigitem'], 10);		// setting for 'config' module only
		hook_add('login.create', [$this, '__login_create'], 99);	// a user has been created. Disable single user?
		hook_add('config.setting.save', [$this, '__settingsave']);	// save a setting, as if it was going through /admin/settings
		hook_add('menu.admin', [$this, '__admin_menu'], 10);
	}

	// if .htconfig file is missing, create it: 
	public function __global_load() {
				// if admin user 
		$hasUser = hook_execute('user.levelpresent', FALSE, 10);
		if (!empty($_SESSION['setup-user']) || !$hasUser) {
			hook_add('user.membership', [$this, '__create_setup_user']);
		}
	}
	
	public function __setupgroups(&$groups) {
		if (empty($groups)) $groups = [];
		$groups[12] = 'setup';
	}

	public function __admin_menu(&$menu) {
		$menu[] = [
				'caption' => 'System Settings', 
				'href' => '/admin/system', 
				'hint' => 'System Settings',
				'icon' => '<i class="fas fa-cog"></i>',
				's' => 0
			];
		$menu[] = [
				'caption' => 'Module Settings', 
				'href' => '/admin/settings', 
				'hint' => 'Module Settings',
				'icon' => '<i class="fas fa-cogs"></i>',
				's' => 0
			];
	}
	
	private function _displayEntry($entry) {
		$function = $entry['function'];
		if (!empty($entry['class'])) $function = $entry['class'] . '::' . $function;
		echo $function . " [{$entry['file']}:{$entry['line']}]\n";
	}
	
	public function __getconfigitem(&$data, $module_name) {
		if ($module_name == 'config') {
			$data = $this->SettingGet('config_module_info', []);
		}
	}
	
	public function __setconfigitem(&$data, $module_name) {
		if ($module_name == 'config') {
			$this->SettingSet('config_module_info', $data);
			$data = TRUE;	// handled
		}
	}
	
	// if the config file is missing database settings, redirect to the settings page
	public function __check(&$uri, $__INPUT, $__OUTPUT) {
        if (($p = strpos($uri, '?')) !== FALSE) $uri = substr($uri, 0, $p);
        $elements = explode('/', $uri);
        $controller = isset($elements[1]) ? $elements[1] : '';
        $method = isset($elements[2]) ? $elements[2] : '';
        if ($controller == 'err' || $controller == '~' || ($controller == 'admin' && $method == 'setup')) return; 
		$db_ok = $this->SettingGet('db_ok', 0);
		$settings = $this->LoadModel('settings_model');
		if (!$db_ok) {
			$settings->PromoteToSetupUser();
			$_SESSION['current_user'] = [ 'u_level' => 12, 'u_id' => -1 ];
			// create lock file/session
			$__OUTPUT->redirect('/admin/setup?db_ok='.$db_ok);
            return;
		}
        // if lock file present, and not lock file user, generate error message. PJY: This did not work
        if ($settings->isLocked()) {
            $uri = 450;
        }

		// Do we have Website Settings?
		if (is_null($this->settings)) {
			// we are still in setup mode  (BUT: this should only be for the initial user/session)
			// create lock user
		}
	}

	public function __create_setup_user(&$permissions) {
		$auth = isset($_GET['auth']) ? $_GET['auth'] : '';
		$settings = $this->LoadModel('settings_model');
		if ($settings->PromoteToSetupUser($auth)) {
			$permissions['setup'] = 1;
		}
	}
	
	public function __nonce_create(&$output, $subject, $key, $ttl = 3600, $single_use = FALSE) {
		if ($output === FALSE) {
			$model = $this->LoadModel('auth_model');
			$output = $model->Authorization_Create($subject, $key, $ttl, $single_use);
		}
	}

	public function __nonce_verify(&$status, $subject, $key, $authorization_text, $noexpire = FALSE) {
		if ($status === FALSE) {
			$model = $this->LoadModel('auth_model');
			$status = $model->Authorization_Verify($subject, $key, $authorization_text, $noexpire);
		}
	}

	public function __public_create(&$output, $subject, $key, $ttl = 3600, $single_use = FALSE) {
		if ($output === FALSE) {
			$model = $this->LoadModel('auth_model');
			$output = $model->Authorization_Create_Private($subject, $key, $ttl, $single_use);
		}
	}
	
	public function __login_create(&$result, $param) {
		if ($result !== NULL) {
			$settings = $this->LoadModel('settings_model');
			$settings->ResetSingleUserMode(intval($result->level));
		}

	}
	
	public function __settingsave(&$result, $key, $requested_auth, $value) {
		if ($result === NULL) {
			$settings = $this->LoadModel('settings_model');
			$res = $settings->ModuleEdit($key, $requested_auth, $value);
			$result = !(isset($res['result']) && $res['result'] == -2);		// ok?
		}
	}
	
	// display a context menu for an input field
	final function context($auth = '') {
		$src = $this->param('src', '');
		$settings = $this->LoadModel('settings_model');
		return $settings->contextMenu($src, $auth);
	}
}

require_once dirname(__DIR__) . '/database/reportobject.php';
