#!/usr/bin/php
<?php

namespace {

ini_set('html_errors', false);

if ($argc < 2) { throw new \Exception('Insufficient arguments'); }

require_once('/usr/share/ombutel/www/includes/cli.php');

}

namespace sync {

use config;
use ombutel\ami;
use ombutel\asterisk;
use ombutel\db;
use ombutel\helper;
use ombutel\settings;
use ombutel\utils;
use ombutel\tenant;
use ombutel\diversion;
use ombutel\extension;
use ombutel\device;

function update_diversion($extension_number, $type, $enabled) {
	// FIXME: whoever calls this doesn't need to update AstDB anymore
	db::begin_transaction();
	if ($extension = extension::find_by_extension($extension_number)) {
		$enabled = ($enabled == 'yes');
		diversion::toggle($extension->extension_id, $type, $enabled);
	}
	db::commit();
}

function set_followme_destination($extension_number, $type, $number) {
	db::begin_transaction();
	if ($extension = extension::find_by_extension($extension_number)) {
		$diversion = diversion::make($extension->extension_id, $type);
		$diversion->number = $number;
		if ($diversion->valid()) {
			$diversion->save();
		}
	}
	db::commit();
}

function set_feature_password($extension, $password) {
	$prefix = config::database_prefix;
	db::query(
		"update `{$prefix}extensions`
		set `features_password` = ?
		where `extension` = ?",
		$password,
		$extension
	);
}

function add_blacklist_entry($callerid, $desc) {
	$prefix = config::database_prefix;
	db::query("insert ignore into `{$prefix}blacklist` (`number`, `description`) values (?, ?)", $callerid, $desc);
}

function remove_blacklist_entry($callerid) {
	$prefix = config::database_prefix;
	db::query("delete from `{$prefix}blacklist` where `number` = ?", $callerid);
}

function set_voicemail_password($extension, $password) {
	$prefix = config::database_prefix;
	db::query(
		"update `{$prefix}extensions`
		set `password` = ?
		where `extension` = ?",
		$password, $extension
	);
	asterisk::generate_voicemail_conf();
}

function reminder($filename, $cos, $did, $when) {
	$tenant = tenant::current()->path;
	$prefix = config::database_prefix;
	$basename = basename($filename);
	@mkdir($folder = "/var/lib/ombutel/static/{$tenant}/reminders", 0777, true);
	rename($filename, $filename = "{$folder}/{$basename}");
	$reminder_id = db::query(
		"insert into `{$prefix}reminders` (`filename`, `did`, `when`) values (?,?,from_unixtime(?))",
		$basename, $did, $when
	)->insert_id;
	$filename_noext = substr($filename, 0, strrpos($filename, '.'));
	file_put_contents($callfile = "/var/spool/asterisk/tmp/reminder-{$reminder_id}.call", <<<EOF
Channel: Local/{$did}@{$cos}
MaxRetries: 2
RetryTime: 60
WaitTime: 30
Callerid: "REMINDER" <{$did}>
Application: Playback
Data: {$filename_noext}
Set: CALL_ORIGIN=feature
Set: __CURRENT_INTERNAL_CID= "REMINDER" <{$did}>
Archive: No
EOF
	);
	touch($callfile, $when, $when);
	rename($callfile, "/var/spool/asterisk/outgoing/reminder-{$reminder_id}.call");
}

function agent_logout_create($extension, $queue_number, $duration, $interface) {
	$when = time() + agent_logout_parse_time($duration);

	$outgoing = '/var/spool/asterisk/outgoing';
	if (!file_exists($outgoing)) {
		if (mkdir($outgoing, 0777, true)) {
			chown($outgoing, 'asterisk');
		}
	}

	$id = time();
	$filename = "{$outgoing}/agent-logout-{$extension}-{$queue_number}-{$id}.call";
	$tmp_filename = tempnam(sys_get_temp_dir(), 'agent-logout');

	file_put_contents($tmp_filename, <<<EOF
Channel: Local/s@sub-auto-logout-agent
MaxRetries: 0
Context: sub-auto-logout-agent
Extension: s
Priority: 1
Archive: no
Set: extension={$extension}
Set: queue=Q{$queue_number}
Set: interface={$interface}

EOF
	);

	// Set the correct timestamp and permissions
	touch($tmp_filename, $when);
	chown($tmp_filename, 'asterisk');
	chgrp($tmp_filename, 'asterisk');

	// Move the file to outgoing directory
	exec("mv {$tmp_filename} {$filename}");
	chmod($filename, 0644);

	return true;
}

function agent_logout_parse_time($time_string) {
	list($hours, $minutes) = explode(':', $time_string);
	return ($hours * 3600) + ($minutes * 60);
}

function hotdesk_login($identity, $technology, $extension) {
	if ($extension = extension::find_by_extension($extension)) {
		if ($device = device::find_by_asterisk_identifier("{$technology}/{$identity}")) {
			$device->login($extension);
		}
	}
}

function hotdesk_logout($identity, $technology, $extension) {
	if ($extension = extension::find_by_extension($extension)) {
		if ($device = device::find_by_asterisk_identifier("{$technology}/{$identity}")) {
			$device->logout($extension);
		}
	}
}

function set_lock_status($extension, $status){
	$prefix = config::database_prefix;
	db::query(
		"update `{$prefix}extensions`
		set `lock` = ?
		where `extension` = ?",
		$status, $extension
	);
}

function set_secretary_status($extension, $status){
	$prefix = config::database_prefix;
	db::query(
		"update `{$prefix}extensions`
		set `absent_secretary` = ?
		where `extension` = ?",
		$status, $extension
	);
}

function set_nightmode_status($nightmode_id, $state){
	$prefix = config::database_prefix;
	db::query(
		"update `{$prefix}nightmodes`
		set `state` = ?
		where `nightmode_id` = ?",
		$state, $nightmode_id
	);
}

function set_nm_all($state) {
	$prefix = config::database_prefix;
	db::query(
		"update `{$prefix}nightmodes`
		set `state` = ?
		where `global_mode` = 'yes'",
		$state
	);
	settings::set('ombutel', 'nm_all_enabled', $state);
}

function add_cc_request($source, $destination){
	$prefix = config::database_prefix;
	db::query(
		"insert into `{$prefix}cc_requests`
			(`source_id`, `destination_id`)
		values (
				(select `extension_id` from `{$prefix}extensions` where `extension` = ?),
				(select `extension_id` from `{$prefix}extensions` where `extension` = ?)
			   )",
		$source, $destination
	);
}

function remove_cc_request($destination){
	$prefix = config::database_prefix;
	db::query(
			"delete from `{$prefix}cc_requests`
			where `destination_id` = (
				select `extension_id` from `{$prefix}extensions` where `extension` = ?
			)
			",
			$destination
	);
}

function limit_extension($extension, $limit_extension) {
	$prefix = config::database_prefix;
	db::query(
		"update `{$prefix}extensions`
		set `limit` = ?
		where `extension` = ?",
		$limit_extension, $extension
	);
}

function ring_device($extension, $devicename, $state) {
	$extension = extension::find_by_extension($extension);
	if (is_null($extension)) {
		return;
	}
	$components = explode('/', $devicename, 2);
	if (count($components) < 2 || !in_array($state, ['yes','no'])) {
		return;
	}
	list($technology, $devicename) = $components;
	if ($technology == 'SIP') {
		db::query(
			"update `ombu_sip_devices` sd
			left join `ombu_devices` d on (d.`device_id` = sd.`device_id`)
			set d.`ring_device` = ?
			where sd.`user` = ?",
			$state, $devicename);
		db::query(
			"update `ombu_cloudphone_devices` cd
			left join `ombu_devices` d on (d.`device_id` = cd.`device_id`)
			set d.`ring_device` = ?
			where cd.`user` = ?",
			$state, $devicename);
		db::query(
			"update `ombu_desktop_devices` dd
			left join `ombu_devices` d on (d.`device_id` = dd.`device_id`)
			set d.`ring_device` = ?
			where dd.`user` = ?",
			$state, $devicename);
	} else if ($technology == 'IAX2') {
		db::query(
			"update `ombu_iax_devices` id
			left join `ombu_devices` d on (d.`device_id` = id.`device_id`)
			set d.`ring_device` = ?
			where id.`user` = ?",
			$state, $devicename);
	} else if ($technology == 'DAHDI') {
		db::query(
			"update `ombu_fxs_devices` fd
			left join `ombu_devices` d on (d.`device_id` = fd.`device_id`)
			left join `ombu_dahdi_channels` c on (c.`channel_id` = fd.`channel_id`)
			set d.`ring_device` = ?
			where c.`global_index` = ?",
			$state, $devicename);
	} else {
		return;
	}
	ami::current()->set_hint("extension-hints", $extension->extension, $extension->hint());
}

function set_last_caller($extension, $number) {
	$prefix = config::database_prefix;
	db::query(
		"update `{$prefix}extensions`
		set `last_caller` = ?
		where `extension` = ?",
		$number, $extension
	);
}

$functions = [
	'enable-CC' => function ($extension) { update_diversion($extension, 'CC', 'yes'); },
	'disable-CC' => function ($extension) { update_diversion($extension, 'CC', 'no'); },
	'enable-BOSS' => function ($extension) { update_diversion($extension, 'BOSS', 'yes'); },
	'disable-BOSS' => function ($extension) { update_diversion($extension, 'BOSS', 'no'); },
	'enable-PEA' => function ($extension) { update_diversion($extension, 'PEA', 'yes'); },
	'disable-PEA' => function ($extension) { update_diversion($extension, 'PEA', 'no'); },
	'enable-FWM' => function ($extension) { update_diversion($extension, 'FWM', 'yes'); },
	'disable-FWM' => function ($extension) { update_diversion($extension, 'FWM', 'no'); },
	'enable-DND' => function ($extension) { update_diversion($extension, 'DND', 'yes'); },
	'disable-DND' => function ($extension) { update_diversion($extension, 'DND', 'no'); },
	'enable-CFI' => function ($extension) { update_diversion($extension, 'CFI', 'yes'); },
	'disable-CFI' => function ($extension) { update_diversion($extension, 'CFI', 'no'); },
	'enable-CFB' => function ($extension) { update_diversion($extension, 'CFB', 'yes'); },
	'disable-CFB' => function ($extension) { update_diversion($extension, 'CFB', 'no'); },
	'enable-CFN' => function ($extension) { update_diversion($extension, 'CFN', 'yes'); },
	'disable-CFN' => function ($extension) { update_diversion($extension, 'CFN', 'no'); },
	'enable-CFU' => function ($extension) { update_diversion($extension, 'CFU', 'yes'); },
	'disable-CFU' => function ($extension) { update_diversion($extension, 'CFU', 'no'); },
	'set-CFI' => function ($extension, $destination) { set_followme_destination($extension, 'CFI', $destination); },
	'set-CFB' => function ($extension, $destination) { set_followme_destination($extension, 'CFB', $destination); },
	'set-CFN' => function ($extension, $destination) { set_followme_destination($extension, 'CFN', $destination); },
	'set-CFU' => function ($extension, $destination) { set_followme_destination($extension, 'CFU', $destination); },
	'feature-password' => __NAMESPACE__ . '\\set_feature_password',
	'blacklist-add' => __NAMESPACE__ . '\\add_blacklist_entry',
	'blacklist-del' => __NAMESPACE__ .  '\\remove_blacklist_entry',
	'voicemail-password' => __NAMESPACE__ . '\\set_voicemail_password',
	'reminder' => __NAMESPACE__ . '\\reminder',
	'hotdesk-login' => __NAMESPACE__ . '\\hotdesk_login',
	'hotdesk-logout' => __NAMESPACE__ . '\\hotdesk_logout',
	'lock-phone' => function ($extension) { set_lock_status($extension, 'yes'); },
	'unlock-phone' => function ($extension) { set_lock_status($extension, 'no'); },
	'absent-secretary' => function ($extension) { set_secretary_status($extension, 'yes'); },
	'enable-secretary' => function ($extension) { set_secretary_status($extension, 'no'); },
	'enable-nm' => function ($nm_id) { set_nightmode_status($nm_id, 'yes'); },
	'disable-nm' => function ($nm_id) { set_nightmode_status($nm_id, 'no'); },
	'toggle_nm_all' => function ($state) { set_nm_all($state); },
	'add-CC' =>  __NAMESPACE__ . '\\add_cc_request',
	'remove-CC' =>  __NAMESPACE__ . '\\remove_cc_request',
	'limit-extension' => __NAMESPACE__ . '\\limit_extension',
	'ring-device' => __NAMESPACE__ . '\\ring_device',
    'last-caller' => __NAMESPACE__ . '\\set_last_caller',
    'agent-logout-create' => __NAMESPACE__ . '\\agent_logout_create',
];

if (!array_key_exists($argv[1], $functions)) { throw new \Exception('Invalid function call'); }

call_user_func_array($functions[$argv[1]], array_slice($argv, 2));

} // namespace sync



?>
