<?php

use Claromentis\Menu;
use Claromentis\Core\Acl;

if (!defined('INSTALL_PROGRESS'))
	die("This file cannot be executed directly");

if (!isset($installer))
	throw new Exception("Install options are not defined");

/** @var $installer \Claromentis\Setup\SetupFacade */

$db = $installer->GetDb();

//$install_options['LICENSE_ID'] = $installer->GetProperty('install.license_id', '', true, "License ID");
$install_options['admin_email'] = $installer->GetProperty('install.admin_email', 'admin.user@claromentis.com', true, 'Admin email');
$install_options['admin_password'] = $installer->GetProperty('install.admin_password', '', true, 'Admin password');
$install_options['admin_password_reset'] = $installer->GetProperty('install.admin_password_reset', false, false, 'Force reset admin password');
$license_email = ($install_options['admin_email'] === 'admin.user@claromentis.com' ? 'license.alert@claromentis.com' : $install_options['admin_email']);
$install_options['license_email'] = $installer->GetProperty('install.license_email', $license_email, true, 'Email address for license notifications');

/**
 * -----------------------------------------------------------------
 * init code
 * -----------------------------------------------------------------
 */
//if (isset($install_options['LICENSE_ID']))
//	$db->query("INSERT INTO variables (var_name, var_value) VALUES ('LICENSE_ID', str:LICENSE_ID)", $install_options['LICENSE_ID']);

$db->query("INSERT INTO variables VALUES ('license_responsible_email', str:email)", $install_options['license_email']);

//Setting default values to user login frozen feature
$db->query("INSERT INTO variables VALUES ('login_attempts','3')");
$db->query("INSERT INTO variables VALUES ('login_frozen_timeout','5')");
$db->query("INSERT INTO variables VALUES ('login_frozen_notify',0)");
$db->query("INSERT INTO variables VALUES ('login_unblock_admin_key','')");

// Primary extranet area and admin user
$query = "INSERT INTO extranet_areas(id, name, description, admin_id, primary_area, logo_file, default_skin) VALUES (1, 'Primary Area', '', 1, 1, '', 1)";
if ($db->type() == 'mssql')
	$query = "SET IDENTITY_INSERT extranet_areas ON; $query; SET IDENTITY_INSERT extranet_areas OFF;";
$db->query($query);


$query = "INSERT INTO users (id, firstname, surname, intranetuser, username, password, ex_area_id, pp_change_next_time) ".
			" VALUES (1, 'Claromentis', 'Administrator', 'yes',  'admin', '".md5($install_options['admin_password'])."', 1, int:admin_password_reset)";  // still using md5, but this will be changed to bcrypt-based hash on first login
if ($db->type() == 'mssql')
	$query = "SET IDENTITY_INSERT users ON; $query; SET IDENTITY_INSERT users OFF;";
$db->query($query, (int) $install_options['admin_password_reset']);

$db->query("UPDATE users SET emailad=str:email WHERE id = 1", $install_options['admin_email']);

// create all admin panels
init_admin_panels($installer);

// Create public calendar
init_calendar_public();

// Holidays planner initialization
init_holiday_days($installer);

// Create stndard metadata sets
init_standard_metadata_sets();

// Users metadata
init_users_metadata();

// Pre-fill users lists configuration
init_users_lists_columns($installer);

// Enable logging all audit events
init_audit_enable_logging();

//Fill default stylesheets for InfoCapture
init_infocapture_stylesheet($installer);

// Create default company links
init_company_links($installer);

// add search suggestion settings
init_search_suggestion($installer);

// set a random minute for telemetry background task to fire
init_telemetry_background_task();

// add main menu
init_add_main_menu();

init_oauth2($installer);

//add integration key templates
init_add_integration_keys($installer);

// Default mail quota
$db->query("INSERT INTO quotas (use_default, quota_type, userid, softlimit, hardlimit, grace, last_warning) VALUES (0, 2, 0, -1, -1, -1, 0)");

// Create default news channel
$db->query("INSERT INTO news_channel (channel_name, is_default) VALUES (str:channel_name, int:is_default)", "General", 1);
$channel_id = $db->insertId();
$perms = new Permissions(PERM_CLASS_NEWS_CHANNEL, $channel_id);
$perms->Add(PERM_VIEW, PERM_OCLASS_ALL);
$perms->Save();

// Add default IP range
$db->query("INSERT INTO ip_ranges VALUES (4, 0, -1, 'Entire world')");

// allow everyone to add new tags
$perms = new Permissions(PERM_CLASS_TAGS_CREATE, 1);
$perms->Add(PERM_VIEW, PERM_OCLASS_ALL);
$perms->Save();

// allow admin to create folders in documents root
$perms = new Permissions(PERM_CLASS_DOCS_ROOT, 1);
$perms->Add(PERM_VIEW, PERM_OCLASS_INDIVIDUAL, 1);
$perms->Save();

// allow admin to create blog channels
$acl = new Acl\Acl(PERM_CLASS_BLOG_CHANNELS_CREATE, 1);
$acl->Add(PERM_VIEW, Acl\PermOClass::INDIVIDUAL, 1);
Acl\AclRepository::I()->Save($acl);

// generate system UUID
$uuid = \Claromentis\Core\Util\UuidGenerator::GenerateVersionFour();
//I don't know why this check is neccessary, but somehow a UUID is being generated before init is run
list($uuid_exists) = $db->query("SELECT COUNT(1) FROM variables WHERE var_name = str:name", 'system_uuid')->fetchAllValues();
if($uuid_exists)
	$db->query("UPDATE variables SET var_value=str:val WHERE var_name=str:name", $uuid, 'system_uuid');
else
	$db->query("INSERT INTO variables (var_value, var_name) VALUES (str:value, str:name)", $uuid, 'system_uuid');

init_data_directories($installer->GetDataDir());
init_local_data_directories($installer->GetLocalDataDir());

/**
 * @param \Claromentis\Setup\SetupFacade $installer
 */
function init_admin_panels($installer)
{
	$db = $installer->GetDb();
	$admin_panels = [
		'system',
		'docs',
		'people',
		'forum',
		'news',
		'blog',
		'audit',
		'rb',
		//'workflow',
		'holidays',
		'company_links',
		'backup',
		'helpdesk',
		'surveys',
		'image_gallery',
		'metadata',
		//'compliances',
		'calendar',
		'extranet',
		'tags',
		'stat',
		'search',
		'oauth2',
		'menu',
		'design',
		'orgchart',
		'communication',
	];
	foreach ($admin_panels as $panel_code)
	{
		$db->query("INSERT INTO simple_acl (object_code, user_id) VALUES (str:code, 1)", $panel_code);
	}
}


function init_calendar_public()
{
	require_once("../common/calendar_pkg.php");
	$user_id = 1;
	$cl = new CalendarCalendar();
	$cl->SetCreator($user_id);
	$cl->SetGroup(CALENDAR_GROUP_GROUP);
	$cl->SetName("Public calendar");
	$cl->SetDescription("Default calendar for public use");
	$cl->SetColor("#03adef");
	if ($cl->Save())
	{
		$cl->GetPermissions()->Add(PERM_VIEW, PERM_OCLASS_ALL);
		$cl->GetPermissions()->Add(PERM_EDIT, PERM_OCLASS_ALL);
		$cl->GetPermissions()->Save();
	}
}

/**
 * @param \Claromentis\Setup\SetupFacade $installer
 */
function init_holiday_days($installer)
{
	$db = $installer->GetDb();
	$db->query("INSERT INTO hpl_days (name , hpl_char , can_decline , can_half_day , limit_action , notify_to , font_color , bg_color , stat, is_system_day) VALUES ('Weekend', '', 0, 0, 0, 0, '#110000', '#FFFF99', 0, 1)");
	$db->query("INSERT INTO hpl_days (name , hpl_char , can_decline , can_half_day , limit_action , notify_to , font_color , bg_color , stat, is_system_day) VALUES ('Usual work day', '', 0, 0, 1, 0, '#CCFFFF', '#CCFFFF', 0, 1)");
	$db->query("INSERT INTO hpl_days (name , hpl_char , can_decline , can_half_day , limit_action , notify_to , font_color , bg_color , stat, is_system_day) VALUES ('Global Holiday', '', 0, 1, 0, 0, '#FFCCCC', '#FFCCCC', 0, 1)");
	$db->query("INSERT INTO hpl_days (name , hpl_char , can_decline , can_half_day , limit_action , notify_to , font_color , bg_color , stat, is_system_day) VALUES ('Global work day', '', 0, 0, 1, 0, '#90FaFa', '#90FaFa', 0, 1)");
	$db->query("INSERT INTO hpl_days (name , hpl_char , can_decline , can_half_day , limit_action , notify_to , font_color , bg_color , stat, is_system_day) VALUES ('Sickness day', 'S', 0, 1, 2, 1, '#FF0000', '#66CC66', 0, 0)");
	$db->query("INSERT INTO hpl_days (name , hpl_char , can_decline , can_half_day , limit_action , notify_to , font_color , bg_color , stat, is_system_day) VALUES ('Unpaid holiday', 'U', 1, 0, 2, 0, '#FF0000', '#FFCCFF', 0, 0)");
	$db->query("INSERT INTO hpl_days (name , hpl_char , can_decline , can_half_day , limit_action , notify_to , font_color , bg_color , stat, is_system_day) VALUES ('Holiday', 'H', 1, 1, 0, 0, '#660033', '#FFCCCC', 0, 0)");
	$db->query("INSERT INTO hpl_days (name , hpl_char , can_decline , can_half_day , limit_action , notify_to , font_color , bg_color , stat , can_over_global, is_system_day) VALUES ('Working extra', 'W', 1, 1, 1, 1, '#000099', '#CCFFFF', 0, 1, 0)");


	$query = "INSERT INTO hpl_group_names (id, name) VALUES (1, 'Default')";
	if ($db->type() == 'mssql')
		$query = "SET IDENTITY_INSERT hpl_group_names ON; $query; SET IDENTITY_INSERT hpl_group_names OFF;";
	$db->query($query);

	$db->query("INSERT INTO hpl_groups (groupid, parent_id, state) VALUES (-1, 0, 1)");
}


function init_standard_metadata_sets()
{
	$common_path = \Claromentis\Core\Services::I()->{'core.common_path'};
	require_once($common_path . "/metadata_pkg.php");

	$set_types_to_add = array(METADATA_SET_GLOBAL, METADATA_SET_DOCUMENT, METADATA_SET_MARKER, METADATA_SET_FOLDER,
	                          METADATA_SET_USER, METADATA_SET_NEWS, METADATA_SET_PUB_PAGE,
	                          METADATA_SET_PUB_FOLDER, METADATA_SET_IMAGE_GALLERY);

	foreach ($set_types_to_add as $set_type)
	{
		$set_obj = new MetaDataSet();
		$set_obj->LoadByType($set_type);
		if (!$set_obj->set_id)
		{
			$set_obj->Save();
		}
	}
}


function init_users_metadata()
{
	global $m_list;

	$set_obj = new MetaDataSet();
	$set_obj->LoadByType(METADATA_SET_USER);

	$users_metadata = array(
		//'usr_rank' => array("User rank", META_TYPE_INT, HTML_COMPONENT_TEXT, false, true, true, false),
		'usr_city' => array("City", META_TYPE_DEFAULT, HTML_COMPONENT_TEXT, true, false, true, false),
		'usr_address' => array("Address", META_TYPE_ADDRESS, HTML_COMPONENT_ADDRESS, true, false, true, false),
		'usr_phone' => array("Landline", META_TYPE_DEFAULT, HTML_COMPONENT_TEXT, true, false, true, false),
		'usr_mobile' => array("Mobile", META_TYPE_DEFAULT, HTML_COMPONENT_TEXT, true, false, true, false),
		'usr_pref_contact' => array("Preferred contact method", META_TYPE_SELECT, HTML_COMPONENT_SELECT, true, false, true, false),
		'usr_career' => array("Career details", META_TYPE_TEXT, HTML_COMPONENT_TEXTAREA, true, false, true, false),
		'usr_interests' => array("Interests", META_TYPE_TEXT, HTML_COMPONENT_TEXTAREA, true, false, true, false),
		'usr_dob' => array("Date of birth", META_TYPE_DATE, HTML_COMPONENT_DATE, true, false, true, false),
		'usr_date_started' => array("Date started", META_TYPE_DATE, HTML_COMPONENT_DATE, true, false, true, false),
	);
	$m_list = array();

	foreach ($users_metadata as $m_key=>$m_info)
	{
		$meta_field = new DynamicMetaFieldPrototype();
		$meta_field->SetName($m_key);
		$meta_field->SetTitle($m_info[0]);
		$meta_field->SetMetaType($m_info[1]);
		$meta_field->SetMetaHtmlType($m_info[2]);
		$meta_field->SetEditable($m_info[3]);
		$meta_field->SetImplicit($m_info[4]);
		$meta_field->SetVisible($m_info[5]);
		$meta_field->SetInheritable($m_info[6]);

		if ($m_key == 'usr_pref_contact')
			$meta_field->values->SetValues(array('Call Landline', 'Call Mobile', 'Email', 'Instant Message', 'SMS'));

		if (!$meta_field->Save())
		{
			echo $meta_field->GetErrMsg()."\n";
		}

		$set_obj->AddMetaField($meta_field);
		$set_obj->Save();

		$m_list[] = '[m]'.$m_key;
	}
	array_shift($m_list);
}

/**
 * @param \Claromentis\Setup\SetupFacade $installer
 */
function init_users_lists_columns($installer)
{
	global $m_list;

	$db = $installer->GetDb();

	// service function
	/**
	 * @param \Claromentis\Core\DAL\Db $db
	 */
	function _t_set_user_field_value($field_name, $column, $value, $db)
	{
		if (substr($field_name, 0, 3) == '[m]')
		{
			$field_name = substr($field_name, 3);
			$is_metadata = 1;
		} else
		{
			$is_metadata = 0;
		}

		list($id) = $db->query_row("SELECT id FROM users_fields WHERE field_name eq:str:field AND is_metadata=int:is_meta", $field_name, $is_metadata ? 1 : 0);
		if (!$id)
		{
			$db->query("INSERT INTO users_fields (field_name, is_metadata, $column) VALUES (str:f_n, int:is_meta, int:val)", $field_name, $is_metadata ? 1 : 0, $value);
			return;
		} else
		{
			$db->query("UPDATE users_fields SET $column=int:val WHERE id=int:id", $value, $id);
		}
	}


	// Now pre-fill users lists configuration

	// My profile page
	$t_myprofile_fields = array_merge(array("firstname", "surname", "emailad", "company", "job_title", "skills", "photo"), $m_list);
	$i = 0; foreach ($t_myprofile_fields as $field)
	{
		_t_set_user_field_value($field, 'my_profile_order', $i++, $db);
		_t_set_user_field_value($field, 'my_profile_editable', 1, $db);
	}


	// Users list
	$t_listpeople_show_fields = array("photo", "fullname", "role", "group", "emailad", "ex_area_id");
	$i = 0; foreach ($t_listpeople_show_fields as $field)
	{
		_t_set_user_field_value($field, 'users_list_order', $i++, $db);
	}


	// Admin users list
	$t_peopleadmin_show_fields = array("fullname", "role", "group", "ex_area_id", "edit_user", "edit_skills", "intranetuser");
	$i = 0; foreach ($t_peopleadmin_show_fields as $field)
	{
		_t_set_user_field_value($field, 'admin_list_order', $i++, $db);
	}


	// Admin "edit user" page
	$t_edituser_fields = array_merge(array("last_time_login", "user_code", "username", "password", "intranetuser", "surname", "firstname",
											"company", "job_title", "emailad", "ex_area_id", "security_level", "whats_new_list", "notification_method", "language",
											"password_policy", "photo", "skin"), $m_list);
	$i = 0; foreach ($t_edituser_fields as $field)
	{
		$editable = ($field == "last_time_login" ? 0 : 1);
		_t_set_user_field_value($field, 'admin_profile_order', $i++, $db);
		_t_set_user_field_value($field, 'admin_profile_editable', $editable, $db);
	}


	// View profile page
	$t_viewprofile_fields = array_merge(array("photo", "company", "skills", '[m]usr_rank'), $m_list);
	$i = 0; foreach ($t_viewprofile_fields as $field)
	{
		_t_set_user_field_value($field, 'view_profile_order', $i++, $db);
	}
	UsersFieldsConfigAdmin::SetFieldsViewProfileTop(array('fullname', 'job_title', 'emailad'));


	// Advanced search
	$t_viewprofile_fields = array_merge(array("firstname", "surname", "role", "group", "ex_area_id", "company", "job_title"), $m_list);
	$i = 0; foreach ($t_viewprofile_fields as $field)
	{
		_t_set_user_field_value($field, 'advanced_search_order', $i++, $db);
	}
}


function init_audit_enable_logging()
{
	global $db;
	$common_path = \Claromentis\Core\Services::I()->{'core.common_path'};
	require_once($common_path . "/audit_functions.php");
	global $audit_structure;

	foreach ($audit_structure as $cid => $t_audit)
	{
		foreach (array_keys($t_audit) as $sid)
		{
			if ($sid == '_name')
				continue;

			$db->query("INSERT INTO audit_conf_txt (category, sub_cat, status) VALUES (str:category, str:sub_cat, 1)", $cid, $sid);
		}
	}
}

/**
 * @param \Claromentis\Setup\SetupFacade $installer
 */
function init_infocapture_stylesheet($installer)
{
    global $INTRANET;

	$db = $installer->GetDb();

    $system_style_files = glob($INTRANET.'/infocapture/css/form.*.css');
    $system_styles = array();
    foreach ($system_style_files as $style_file)
    {
        $system_styles[] = array(
            'name' => ucfirst(substr(basename($style_file,'.css'),5)),
            'style' => file_get_contents($style_file)
        );
    }

    foreach ($system_styles as $system_style)
    {
        $style = array(
            'str:name' => $system_style['name'],
            'clob:style' => $system_style['style']
        );
        $db->query(new \Claromentis\Core\DAL\QueryInsert('fb_form_css', $style));
    }
}

/**
 * @param \Claromentis\Setup\SetupFacade $installer
 */
function init_company_links($installer)
{
	$db = $installer->GetDb();
	$infobar_links = array(
		array('Claromentis', 'http://www.claromentis.com/', true),
		//array('Rooms booking', '/intranet/rooms/'),
		//array('Holidays planner', '/intranet/holidays/'),
		//array('Forms', '/intranet/forms/forms.php'),
	);
	$order = 0;
	foreach ($infobar_links as $item)
	{
		$db->query("INSERT INTO infobar_menu_item (title, url, display_order, new_window) VALUES (str:new_menu_name, str:new_link, int:max_order, int:add_new_window)", $item[0], $item[1], $order++, $item[2] ? 1 : 0);
		$id = $db->insertId();
		$perms = new Permissions(PERM_CLASS_INFOBAR, $id);
		$perms->Add(PERM_VIEW, PERM_OCLASS_ALL);
		$perms->Save();
	}
}


function init_data_directories($data_dir)
{
	if (!is_dir($data_dir))
		throw new Exception("Undefined DATA_DIR");

	/**
	* -----------------------------------------------------------------
	* Create directories and set correct rights
	* -----------------------------------------------------------------
	*/
	$directories = array(
		'appdata',
		'audit_archive',
		'backup',
		'config',
		'diagram_cache',
		'discussion',
		'discussion/tmp',
		'docs_data',
		'forum_data',
		'fuu_files',
		'gallery',
		'helpdesk_files',
		'audit_archive',
		'mail',
		'metadata_files',
		'survey_data',
		'room_booking',
		'room_booking/room',
		'room_booking/fac',
	);


	foreach ($directories as $dir)
	{
		if (!is_dir($data_dir . "/$dir"))
			mkdir($data_dir . "/$dir");
	}

	init_chmod_R($data_dir, 0777);
}

function init_local_data_directories($data_dir)
{
	if (!is_dir($data_dir))
		throw new Exception("Undefined local DATA_DIR");

	/**
	 * -----------------------------------------------------------------
	 * Create directories and set correct rights
	 * -----------------------------------------------------------------
	 */
	$directories = array(
		'i18n_cache',
		'templater_cache',
		'temp',
		'logs',
		'export',
		'import'
	);

	foreach ($directories as $dir)
	{
		if (!is_dir($data_dir . "/$dir"))
			mkdir($data_dir . "/$dir");
	}

	init_chmod_R($data_dir, 0777);
}

/**
 * @param \Claromentis\Setup\SetupFacade $installer
 */
function init_search_suggestion($installer)
{
	$db = $installer->GetDb();
	$db->query(new \Claromentis\Core\DAL\QueryInsert('variables', array('str(255):var_name' => 'search_suggestion_notify_admin', 'str:var_value' => 1)));
	$db->query(new \Claromentis\Core\DAL\QueryInsert('variables', array('str(255):var_name' => 'search_suggestion_notify_user', 'str:var_value' => 1)));
}

/**
 * @param \Claromentis\Setup\SetupFacade $installer
 */
function init_add_main_menu()
{
	$menu_code = 'main_menu';

	$menu = new Menu\PublishMenu();
	$menu->SetLocation(Menu\MenuLocation::INTRANET);
	$menu->SetDepthLimit(3);
	$menu->SetTitle($menu_code);
	$menu->Save();

	$menu_id = $menu->GetId();

	$acl = new Acl\Acl(PERM_CLASS_PUBLISH_MENU, $menu_id);
	$acl->Add(PERM_VIEW, Acl\PermOClass::INDIVIDUAL, 1); // give admin rights to edit menu
	Acl\AclRepository::I()->Save($acl);
}

/**
* More functional wrapper for PHP chmod function
*
* @param string $path path for file/directory
* @param int $filemode UNIX file mode like 0755
* @return boolean
*/
function init_chmod_R($path, $filemode)
{
	if (!is_dir($path))
		return @chmod($path, $filemode);

	$dh = opendir($path);

	while ($file = readdir($dh))
	{
		if ($file != '.' && $file != '..')
		{
			$fullpath = $path . '/' . $file;

			if (!is_dir($fullpath))
			{
				if (!@chmod($fullpath, $filemode))
					return false;
			}
			else
			{
				if (!init_chmod_R($fullpath, $filemode))
					return false;
			}
		}
	}

	closedir($dh);

	if (@chmod($path, $filemode))
		return true;
	else
		return false;
}

function init_telemetry_background_task()
{
	// set the telemetry payload to be generated and sent at a random minute in
	// the hour between 3 and 4am on Mondays
	$minute = mt_rand(1, 59);
	DBVar::Set('telemetry_bg_minute', $minute);
}

function init_oauth2($installer)
{
	require_once('../oauth2/classes/UseCase/CreateKeys.php');

	/** @var \Claromentis\Setup\SetupFacade $installer */
	$use_case = new \Claromentis\OAuth2\UseCase\CreateKeys($installer->GetDataDir());

	$use_case->CreateKeys();
}

/**
 * @param \Claromentis\Setup\SetupFacade $installer
 */
function init_add_integration_keys($installer)
{
	$db = $installer->GetDb();
	// templates for initial keys which will be available in Claromentis
	$initial_keys = array(
		'google_maps' => ['Google Maps API Key','Created in the Google Developer console','{"api_key":"xxxxxxxx"}'],
		'mailgun' => ['Mailgun API Key', 'Obtained from mailgun.com', '{"api_key":"xxxxxxxx"}'],
		'google_picker' => ['Google Picker key and OAuth details','Needs a client_id and app_id as well as the developer_key. All can be created in the Google Developer console.','{"developer_key":"xxxxxxxxxx","client_id":"xxxxxxxxx","app_id":"xxxxxxxxx"}'],
		'cloudflare_turnstile' => ['Cloudflare Turnstile CAPTCHA','Get your secret key at https://dash.cloudflare.com/?to=/:account/turnstile','{"secret_key":"xxxxxxxxxx","site_key":"xxxxxxxxxx"}'],
	);

	foreach	($initial_keys as $key => $value)
	{
		$db->query('INSERT INTO integration VALUES (str:api_name, str:description, str:help_text, str:json_data)', $key, $value[0], $value[1], $value[2]);
	}
}
