<?php

require_once dirname(__FILE__) . '/../../lib/phoneprovisioning.php';


require_once "siemens.php";
require_once 'WorkpointMessage.php';
require_once 'DLSMessage.php';
require_once 'ConfigItem.php';
require_once "TimezoneHelper.php";

function _get_response_headers_as_string()
{
    global $_SERVER;
    if (!function_exists('headers_list')) {
        //gs_log( GS_LOG_DEBUG, 'Can\'t get response headers (PHP < 5)' );
        return false;
    }
    $ret = '';
    $ret .= $_SERVER['SERVER_PROTOCOL'] . ' 200 OK' . "\r\n";
    $headers = headers_list();
    foreach ($headers as $header) {
        $ret .= $header . "\r\n";
    }
    $ret .= "\r\n";
    return $ret;
}

function _get_request_headers_as_string()
{
    global $_SERVER, $orig_url;
    $ret = '';
    $ret .= $_SERVER['REQUEST_METHOD'] . ' ' . $orig_url . ' ' . $_SERVER['SERVER_PROTOCOL'] . "\r\n";
    foreach ($_SERVER as $k => $v) {
        if (subStr($k, 0, 5) === 'HTTP_') {
            $k = str_replace(' ', '-', ucWords(str_replace('_', ' ', strToLower(subStr($k, 5)))));
            $ret .= $k . ': ' . $v . "\r\n";
        }
    }
    $ret .= "\r\n";
    return $ret;
}

function siemens_prov_error_handler($type, $msg, $file, $line)
{
    Log::e($type . " " . $msg . " " . $file . ":" . $line, "siemens-dls");
}
set_error_handler('siemens_prov_error_handler');

class SiemensPhoneProvisioning extends VirtualPhoneProvisioningController
{

    private $answer = null;
    private $filesToDeploy = array();
    private $filesAreDeployed = array();

    protected function getProvURL($mac = null)
    {
        return "https://" . cfg('PROV_HOST') . ":18443";
    }

    protected function checkMacAddress($mac)
    {
        $mac = str_replace(":", "", $mac); // remove :
        return parent::checkMacAddress($mac);
    }

    protected function checkUserAgent($ua)
    {
        return true;
    }

    protected function outputMessage(DLSMessage $dlsmessage)
    {
        ob_start();
        echo $dlsmessage->xml() . "\n\n";
        header('X-Powered-By: Phonalisa DLS');
        header('Content-Type: text/xml');
        header('Content-Length: ' . (int) @ob_get_length());
        Log::d("[" . Yii::app()->session["mac-addr"] . "] outputMessage: " . _get_response_headers_as_string() . "\n" . $dlsmessage->xml(), "siemens-dls");
        @ob_flush();
    }

    private function getSecureDownloadHost()
    {
        $ports = cfg('PROV_PORT_SECURE');
        if ($ports == "" || $ports == "443") {
            return cfg('PROV_HOST');
        } else {
            return cfg('PROV_HOST') . ":" . $ports;
        }
    }

    private function readWorkPointMessagePost()
    {
        $raw_post = file_get_contents('php://input');
        if (trim($raw_post) == '') {
            Log::e("No post data!", "siemens-dls");
            Yii:app()->end();
        }

        Log::d("Phone Says: " . _get_request_headers_as_string() . "\n" . $raw_post, "siemens-dls");
        $message = new WorkpointMessage($raw_post);
        return $message;
    }

    private function getPhoneModelForDeviceName($name)
    {
        foreach ($this->_getSupportedPhoneModels() as $model) {
            if ($model->getUserAgent() == Yii::app()->session["device-type"]) {
                Log::d("[" . Yii::app()->session["mac-addr"] . "] found model class for: " . Yii::app()->session["device-type"], "siemens-dls");
                return $model;
            }
        }
        Log::e("[" . Yii::app()->session["mac-addr"] . "] no Phone Model class found for: " . Yii::app()->session["device-type"], "siemens-dls");
        return NULL;
    }

    private function normalizeFirmwareVersion($version)
    {
        $normalized = "";
        $m = array();
        if (preg_match("/^V?(\d+)(?:\s*|\.)R?(\d+)\.(\d+)\.(\d+)/i", $version, $parts)) {
            $normalized .= str_pad($parts[1], 2, '0', STR_PAD_LEFT) . '.' .
                    str_pad($parts[2], 2, '0', STR_PAD_LEFT) . '.' .
                    str_pad($parts[3], 2, '0', STR_PAD_LEFT) . '.' .
                    str_pad($parts[4], 2, '0', STR_PAD_LEFT);
        }

        return $normalized;
    }

    private function psetting($key, $value = "", $index = null)
    {
        $configItem = new ConfigItem();
        $configItem->name = $key;
        $configItem->value = $value;
        $configItem->index = $index;
        $this->answer->addItem($configItem);
    }

    public function run($controller)
    {
        $mController = $controller;
        Log::d("start run()", "siemensDebug");
        $session = Yii::app()->getSession();
        $session->setSessionName('JSESSIONID');
        $session->setCookieMode('only');

        $param = array();
        $param["lifetime"] = 0;
        $param["path"] = "/DeploymentService/";
        $param["domain"] = "";
        $param["secure"] = 1;
        $param["httponly"] = 0;
        $session->setCookieParams($param);
        $session->open();
        Log::d("openSession", "siemensDebug");
        $msg = $this->readWorkPointMessagePost();
        Log::d("readWorkPointMessagePost()", "siemensDebug");
        if ($msg->action == DLSMessage::ActionReadAllItems) {

            Log::d("msg->action = DLSMessage::ActionReadAllItems", "siemensDebug");

            Log::v("[" . Yii::app()->session["mac-addr"] . "] Read all Items requested", "siemens-dls");
            $this->answer = new DLSMessage($msg->nonce);
            $this->answer->setAction(DLSMessage::ActionWriteItems);

            Log::d("checkMacAddress()", "siemensDebug");
            $this->checkMacAddress(Yii::app()->session["mac-addr"]);

            Log::d("checkIfRequesterIsAllowedInNetwork()", "siemensDebug");
            $this->checkIfRequesterIsAllowedInNetwork();

            Log::d("getPhoneModelForDeviceName()", "siemensDebug");
            $model = $this->getPhoneModelForDeviceName(Yii::app()->session["device-type"]);
            if ($model == NULL) {
                return;
            }

            Log::d("setCurrentPhoneModel()", "siemensDebug");
            $this->setCurrentPhoneModel($model);
            Log::d("setCurrentFirmwareVersion()", "siemensDebug");
            $this->setCurrentFirmwareVersion($this->normalizeFirmwareVersion(Yii::app()->session["software-version"]));

            // Get initial phone model
            Log::d("getPhoneModel()", "siemensDebug");
            $this->getPhoneModel();
            Log::d("setProvisioningJobStarted()", "siemensDebug");
            $this->setProvisioningJobStarted();
            $this->changeExpireTimeIfExpireRangeChanged();
            if ($this->mCurrentProvisioningJob != NULL) { // save job id into session
                Log::d("mCurrentProvisioningJob() != NULL", "siemensDebug");
                Yii::app()->session["prov-job-id"] = $this->mCurrentProvisioningJob->id;
            }
            Log::d("checkFirmwareUpdates() != NULL", "siemensDebug");
            $firmwareUpdates = $this->checkFirmwareUpdates($msg->nonce);
            if ($firmwareUpdates !== false) { // run firmware update first (file deployment)
                Log::d("firmwareUpdates !== false", "siemensDebug");
                $this->answer = $firmwareUpdates;
            } else {
                Log::d("firmwareUpdates === false", "siemensDebug");
                $this->setPhonalisaProvisioningVariables();
                Log::d("loadConfigValues", "siemensDebug");
                $this->loadConfigValues();
                Log::d("checkFilesToDelete", "siemensDebug");
                $deleteFiles = $this->checkFilesToDelete($msg->nonce);
                if ($deleteFiles !== false) {
                    Log::v("[" . Yii::app()->session["mac-addr"] . "] Now deleting unused files.", "siemens-dls");
                    Log::d("answer = deleteFiles", "siemensDebug");
                    $this->answer = $deleteFiles;
                } else if (count($this->filesToDeploy) > 0) { // deploy all files first:
                    Log::d("if (count(this->filesToDeploy)", "siemensDebug");
                    //Log::v("[".Yii::app()->session["mac-addr"]."] filesToDeploy: ".print_r($this->filesToDeploy, true),"siemens-dls");

                    Log::d("array_shift(filesToDeploy)", "siemensDebug");
                    $file = array_shift($this->filesToDeploy);
                    //Log::v("[".Yii::app()->session["mac-addr"]."] FILE: ".print_r($this->filesToDeploy, true),"siemens-dls");

                    Log::d("answer = new DLSMessage", "siemensDebug");
                    $this->answer = new DLSMessage($msg->nonce);
                    $this->answer->setAction(DLSMessage::ActionFileDeployment);
                    Log::v("[" . Yii::app()->session["mac-addr"] . "] Now deploying file: " . $file["name"], "siemens-dls");

                    Log::d("psetting(file-type, file[type]);", "siemensDebug");
                    $this->psetting("file-type", $file["type"]);
                    if ($file["type"] == "LOGO" || $file["type"] == "SCREENSAVER") {
                        $this->psetting("file-https-base-url", "https://" . $this->getSecureDownloadHost() . "/pictures/" . $file["name"]); //FIXME URL!
                    } else if ($file["type"] == "LDAP") {
                        $this->psetting("file-https-base-url", "https://" . $this->getSecureDownloadHost() . "/ldap/" . $file["name"]); //FIXME URL!
                    } else {
                        $this->psetting("file-https-base-url", "https://" . $this->getSecureDownloadHost() . "/ringtone/" . $file["name"]); //FIXME URL!
                    }
                }
            }
        } else if ($msg->action == DLSMessage::ActionWriteItems && $msg->status == "accepted") {
            Log::d("action == DLSMessage::ActionWriteItems ", "siemensDebug");
            Log::v("[" . Yii::app()->session["mac-addr"] . "] Write Items accepted. Sending Cleanup", "siemens-dls");
            $this->answer = new DLSMessage($msg->nonce);
            $this->answer->setAction(DLSMessage::ActionCleanup);
            if (Yii::app()->session["prov-job-id"] != "") {
                Log::d("session[prov-job-id] != null ", "siemensDebug");
                $this->mCurrentProvisioningJob = Job::model()->findByPk(Yii::app()->session["prov-job-id"]);
            }
            Log::d("setProvisioningJobFinished", "siemensDebug");
            $this->setProvisioningJobFinished();
            $this->setLastProvTimestampToPhonesModel();
        } else if ($msg->action == DLSMessage::ActionWriteItems && $msg->status == "busy") {
            Log::d("action == DLSMessage::ActionWriteItems", "siemensDebug");
            $this->answer = new DLSMessage($msg->nonce);
            $this->answer->setAction(DLSMessage::ActionCleanup);

            if (Yii::app()->session["prov-job-id"] != "") {
                $this->mCurrentProvisioningJob = Job::model()->findByPk(Yii::app()->session["prov-job-id"]);
            }
            Log::d("setProvisioningJobNeedToTriggerAgain", "siemensDebug");
            $this->setProvisioningJobNeedToTriggerAgain();
        } else { // phone is contacting us, so say it has to read all items
            Log::d("phone is contacting us, so say it has to read all items", "siemensDebug");
            if ($msg->reasonForContact == "local-changes") {
                Log::d("$msg->reasonForContact == local changes", "siemensDebug");
                Log::v("[" . $msg->items["mac-addr"] . "] Siemens " . $msg->items["device-type"] . " [" . $msg->items["software-version"] . "] contacts us, cause: " . $msg->reasonForContact . " - ignored.", "siemens-dls");
                $this->answer = new DLSMessage($msg->nonce);
                $this->answer->setAction(DLSMessage::ActionCleanup);
            } else {
                Log::d("$msg->reasonForContact != local changes", "siemensDebug");
                Log::v("[" . $msg->items["mac-addr"] . "] Siemens " . $msg->items["device-type"] . " [" . $msg->items["software-version"] . "] contacts us, cause: " . $msg->reasonForContact, "siemens-dls");
                $this->answer = new DLSMessage($msg->nonce);
                $this->answer->setAction(DLSMessage::ActionReadAllItems);
            }
        }
        Log::d("outputMessage", "siemensDebug");
        $this->outputMessage($this->answer);
        Yii:app()->end();
    }

    private function checkFilesToDelete($nonce)
    {
        // check files on phone, and check if they are belong to us:
        $filesOnPhone = Yii::app()->session["file-deployment-name"];
        $filesOnPhoneWhichAreDeleted = Yii::app()->session["file-deployment-action"];
        $filesOnPhoneTypes = Yii::app()->session["file-deployment-type"];
        $filesToBeDeleted = array();

        //Log::v("[".Yii::app()->session["mac-addr"]."] Files on Phone: ".print_r($filesOnPhone,true), "siemens-dls");
        //Log::v("[".Yii::app()->session["mac-addr"]."] Files on Phone which are deleted: ".print_r($filesOnPhoneWhichAreDeleted,true), "siemens-dls");

        foreach ($filesOnPhone as $key => $fileOnPhone) {
            if (!array_key_exists($fileOnPhone, $this->filesToDeploy) && !array_key_exists($fileOnPhone, $this->filesAreDeployed)) {

                if ($filesOnPhoneWhichAreDeleted[$key] != "delete") {
                    Log::v("[" . Yii::app()->session["mac-addr"] . "] File: " . $fileOnPhone . " does not belongs to this phone and will be deleted from memory.", "siemens-dls");
                    $definition = array();
                    $definition["type"] = $filesOnPhoneTypes[$key];
                    $definition["name"] = $filesOnPhone[$key];
                    $filesToBeDeleted[$key] = $definition;
                }
            }
        }

        if (count($filesToBeDeleted) == 0) {
            return false;
        }

        $this->answer = new DLSMessage($nonce);
        $this->answer->setAction(DLSMessage::ActionFileDeployment);
        $index = 1;
        foreach ($filesToBeDeleted as $fileToBeDeleted) {
            Log::v("[" . Yii::app()->session["mac-addr"] . "] Now deleting file: " . $fileToBeDeleted["name"], "siemens-dls");
            $this->psetting("file-name", $fileToBeDeleted["name"], $index);
            $this->psetting("file-type", $fileToBeDeleted["type"], $index);
            $this->psetting("file-action", "delete", $index);
            //$deleteMsg->addItem($item)
            ++$index;
        }
        return $this->answer;
    }

    private function deployFile($name, $type)
    {
        $deployedFiles = Yii::app()->session["file-deployment-name"];
        //Log::v("[".Yii::app()->session["mac-addr"]."] TEST: ".print_r($deployedFiles,true), "siemens-dls");

        if (is_array($deployedFiles) && in_array($name, $deployedFiles)) {
            Log::v("[" . Yii::app()->session["mac-addr"] . "] File: " . $name . " is currently deployed.", "siemens-dls");
            $this->filesAreDeployed[$name] = $name;
            return;
        }

        Log::v("[" . Yii::app()->session["mac-addr"] . "] File: " . $name . " is marked to deploy.", "siemens-dls");
        // add files to the todo list...
        $upload = array();
        $upload["type"] = $type;
        $upload["name"] = $name;
        $this->filesToDeploy[$name] = $upload;
    }

    protected function checkFirmwareUpdates($nonce)
    {
        // get current firmware version
        if ($this->mCurrentFirmwareVersion == "") {
            Log::w("[" . Yii::app()->session["mac-addr"] . "] Could not check Firmware Version (Phone has not reported one!).", "siemens-dls");
            return false;
        }

        $Phone = $this->getPhoneModel();
        $firmware = NULL;
        if ($Phone->firmware_update_key != null && $Phone->firmware_update_key != "") {
            //load firmware
            $firmware = Firmware::model()->findByPk($Phone->firmware_update_key);
            if ($firmware != NULL) {
                if ($firmware->version == $this->mCurrentFirmwareVersion) {
                    Log::v("[" . Yii::app()->session["mac-addr"] . "] Firmware on Phone (" . $this->mCurrentFirmwareVersion . " is the same as the manual selected Firmware (" . $firmware->version . ").", "siemens-dls");
                    return false;
                }
            } else {
                Log::v("[" . Yii::app()->session["mac-addr"] . "] Firmware was set Manually for Phone but the firmware file seams to does not exists any more, fallback to default firmware.", "siemens-dls");
            }
        }

        if ($firmware == NULL) { // no manual update was found
            $attributes = array();
            $attributes["phoneType"] = $this->mCurrentPhoneModel->getPhoneModelName();
            $attributes["standard"] = "1";

            $firmwares = Firmware::model()->findAllByAttributes($attributes, 1);
            if (count($firmwares) == 0) {
                Log::v("[" . Yii::app()->session["mac-addr"] . "] No Firmware-file is available and set to standard for Phone.", "siemens-dls");
                return false;
            }
            $firmware = $firmwares[0];
            if ($firmware->version == $this->mCurrentFirmwareVersion) {
                Log::v("[" . Yii::app()->session["mac-addr"] . "] Firmware on Phone (" . $this->mCurrentFirmwareVersion . " is the same as the standard Firmware (" . $firmware->version . ").", "siemens-dls");
                return false;
            }

            Log::v("[" . Yii::app()->session["mac-addr"] . "] Firmware on Phone (" . $this->mCurrentFirmwareVersion . " differs from default Firmware (" . $firmware->version . "). Scheduling an update...", "siemens-dls");
        } else {
            Log::v("[" . Yii::app()->session["mac-addr"] . "] Firmware on Phone (" . $this->mCurrentFirmwareVersion . " differs from manuel set Firmware (" . $firmware->version . "). Scheduling an update...", "siemens-dls");
        }

        //OS_60_SIP_V3_R1_41_0.img
        $this->answer = new DLSMessage($nonce);
        $this->answer->setAction(DLSMessage::ActionSoftwareDeployment);

        Log::v("[" . Yii::app()->session["mac-addr"] . "] Updating Firmware to: " . $firmware->version . " (" . $firmware->fileName . ")", "siemens-dls");
        $this->psetting("file-type", "APP");
        $this->psetting("file-https-base-url", "https://" . $this->getSecureDownloadHost() . "/firmware/" . $firmware->fileName); //FIXME URL!
        $this->psetting("file-sw-type", "Siemens SIP");
        $this->psetting("file-sw-version", $firmware->version);
        $this->psetting("file-priority", "normal");

        return $this->answer;
    }

    protected function loadConfigValues($__mac = null)
    {
        $Phone = $this->getPhoneModel();

        $PhoneType = $this->mCurrentPhoneModel->getPhoneModelName();
        Log::v("[" . Yii::app()->session["mac-addr"] . "] Phone is an " . $PhoneType, "siemens-dls");
        $SipAccount = $Phone->getSipAccount();

        $User = $SipAccount->getUser();

        $provisioningProfile = $this->getProvisioningProfiles($User);

        //$SipAccount
        // set registrar authname and password
        $this->psetting('e164', $SipAccount->authname);
        $this->psetting('sip-user-id', $SipAccount->authname);

        $this->psetting('sip-pwd', $SipAccount->secret);
        $this->psetting('sip-name', $SipAccount->getLabel());
        $this->psetting('register-by-name', 'false');

        $this->psetting('reg-addr', $SipAccount->getSIPRegistrar());
        $this->psetting('reg-port', cfg('INTERNAL_SIP_PORT'));

        $this->psetting('registrar-addr', $SipAccount->getSIPRegistrar());
        $this->psetting('registrar-port', cfg('INTERNAL_SIP_PORT'));

        // TLS
        if (cfg("INTERNAL_SSL_ENABLE") == "1") {
            $this->psetting('voip-server-validation', 'false');
            $this->psetting('sip-transport-user', '2');
            $this->psetting('reg-port', cfg('INTERNAL_TLS_PORT'));
            $this->psetting('registrar-port', cfg('INTERNAL_TLS_PORT'));
        } else {
            $this->psetting('sip-transport-user', '0');
        }

        $this->psetting('realm', 'phonalisa.local');

        $this->psetting('uaCSTA-enabled', 'true'); // Yes! We're supporting uaCSTA!
        $this->psetting('auto-answer', 'true'); // Yes! We're supporting uaCSTA!
        $this->psetting('beep-on-auto-answer', 'true'); // Yes! We're supporting uaCSTA!

        $this->psetting('reg-ttl', "$SipAccount->expires");

        $this->psetting('moh-enabled', 'false');
        $this->psetting('voice-mail-e164', 'voicemail');

        $this->psetting('server-type', '0');

        // Call recording
        $this->psetting('call-record-auto-start', 'false');
        $this->psetting('call-record-all-calls', 'false');
        $this->psetting('feature-availability', 'true', '24');
        $this->psetting('call-record-phone-number', 'callrecorder');

        // Display stuff
        $this->psetting('display-id-unicode', $SipAccount->getShortLabel());
        $this->psetting('use-display-id', "true");

        if ($User) {
            $this->psetting('ldap-transport', '0');
            $this->psetting('ldap-server-port', '12389');
            $this->psetting('ldap-server-address', $SipAccount->getSIPRegistrar());
            $this->psetting('ldap-authentication', '1');
            $this->psetting('ldap-user', 'cn=' . $User->name . ",dc=default");
            $this->psetting('ldap-pwd', '439rz9f4uifh8vsfdpugh4');
            $this->psetting('display-skin', "0");
        } else {
            $this->psetting('display-skin', "1");
        }
        $this->deployFile("ldap.txt", "LDAP");

        // Country and Language
        $language = cfg("GUI_LANGS");
        if ($User && $User->user_language != "") {
            $language = $User->user_language;
        }
        $language_iso = $this->phonalisaLanguageToSiemensLanguage($language);
        $this->psetting('language-iso', $language_iso);
        $this->psetting('country-iso', strtoupper($language_iso));

        $language = cfg("GUI_LANGS");
        if ($User && $User->user_language != "") {
            $language = $User->user_language;
        }

        $dateformat = cfg("USER_DATE_FORMAT");
        if ($User && $User->user_date_format != "") {
            $dateformat = $User->user_date_format;
        }

        if ($dateformat == "dd.MM.yyyy") {
            $dateformat = "0";
        } else if ($dateformat == "yyyy-MM-dd") {
            $dateformat = "1";
        } else if ($dateformat == "MM/dd/yyyy") {
            $dateformat = "2";
        } else {
            $dateformat = "0";
        }
        $this->psetting('date-format', $dateformat);  // DD.MM.YYYY //FIXME get standard Date format with best match
        //codec negotation
        $this->psetting('allow-hd-icon-display', 'true');
        $this->psetting('codec-type', '2', '3'); // G729
        $this->psetting('codec-type', '1', '2'); // G722
        $this->psetting('codec-type', '0', '1'); // G711
        // disallow allow G729
        $this->psetting('codec-allowed', 'false', '3'); // G729
        // check codec settings from system
        $codecs_allowed = cfg("GLOBAL_CODEC_PREFS");
        if ($codecs_allowed == "") {
            $codecs_allowed = "G711,G722";
        }

        $codecs_array = explode(",", $codecs_allowed);

        // allow allow G711 and G722
        if (in_array("G722", $codecs_array)) {
            $this->psetting('codec-allowed', 'true', '2'); // G722
        }

        if (in_array("PCMA", $codecs_array)) {
            $this->psetting('codec-allowed', 'true', '1'); // G711
        }

        // set ranking of G722 to first position
        $this->psetting('codec-rank', '1', '2'); // G722
        $this->psetting('codec-rank', '2', '1'); // G711
        // SRTP
        $this->psetting('srtp-key-negotiation-method', '1');
        $this->psetting('secure-call-payload-options', '0');

        if (cfg("RTP_ENABLE_SRTP") == "1") {
            $this->psetting('srtp-encryption-allowed', 'true', '1');
            $this->psetting('voip-payload-security-allowed', 'true');
        } else {
            $this->psetting('srtp-encryption-allowed', 'false', '1');
            $this->psetting('voip-payload-security-allowed', 'false');
        }

        // Date and Time
        $this->psetting('auto-daylight-save', 'true');
        $this->psetting('daylight-save', 'true');
        $this->psetting('daylight-save-minutes', '60');
        $this->psetting('daylight-save-zone-id', '9');

        //disable FPK Long press:
        $this->psetting('fpk-long-press-timer', '0');

        // Set BLF code
        $this->psetting('blf-code', cfg("DP_PICKUP_PREFIX"));

        // Callwaiting on/off
        if ($User && $User->call_waiting) {
            $this->psetting('call-waiting-enabled', 'true');
        } else {
            $this->psetting('call-waiting-enabled', 'false');
        }

        if ($User && $User->key_tone) {
            $this->psetting('click-keys', '1');
            $this->psetting('key-click-volume', '2');
        } else {
            $this->psetting('click-keys', '0');
            $this->psetting('key-click-volume', '0');
        }

        // set timezone settings
        $this->psetting("auto-daylight-save", "true");
        $this->psetting("conference-factory-uri", "");
        $this->psetting("daylight-save-minutes", "60");

        $tz = cfg("TIMEZONE");
        if ($User && $User->user_timezone != "") {
            $tz = $User->user_timezone;
        }
        $tz_offset = get_timezone_offset("UTC", $tz, true);
        $this->psetting("sntp-tz-offset", $tz_offset * 60);
        $this->psetting("sntp-addr", cfg("NTP_HOST"));

        $time_format = cfg("USER_TIME_FORMAT");
        if ($User && $User->user_time_format != "") {
            $time_format = $User->user_time_format;
        }

        if ($time_format == "24") {
            $this->psetting('time-format', "0");
        } else {
            $this->psetting('time-format', "1");
        }

        for ($tone = 1; $tone < 9; $tone++) {
            $this->psetting('alert', "ringtone-" . $tone . "^" . $tone . "^2^60^" . $tone, $tone);
        }

        $this->psetting('alert', "mute^0^2^60^0", 9);


        // check ringtones
        if ($User && $User->ringtone_int != null && $User->ringtone_int != "" && $User->ringtone_int != "mute" && !startsWith($User->ringtone_int, "ringtone")) {
            $this->deployFile($User->ringtone_int, "RINGTONE");
            $this->psetting('alert', "alert-internal^7^2^60^" . $User->ringtone_int, 10);
        }

        if ($User && $User->ringtone_ext != null && $User->ringtone_ext != "" && $User->ringtone_ext != "mute" && !startsWith($User->ringtone_ext, "ringtone")) {
            $this->deployFile($User->ringtone_ext, "RINGTONE");
            $this->psetting('alert', "alert-external^7^2^60^" . $User->ringtone_ext, 11);
        }

        if ($User && $User->ringtone_queue != null && $User->ringtone_queue != "" && $User->ringtone_queue != "mute" && !startsWith($User->ringtone_queue, "ringtone")) {
            $this->deployFile($User->ringtone_queue, "RINGTONE");
            $this->psetting('alert', "alert-queue^7^2^60^" . $User->ringtone_queue, 12);
        }

        // Check XML Apps
        if ($User) {
            $this->addXmlPhonebook(@$Phone->mac_addr);
//            $this->addXmlConfigApp(@$Phone->mac_addr);    // add this if Xml-Config-App is running again
        } else {
            $this->psetting('XML-app-action', 'delete', '1'); //delete XmlPhonebook-App
//            $this->psetting('XML-app-action', 'delete', '2'); //delete XmlConfig-App
        }
        // Check Keys
        $this->processSoftkeys();

        // Get prov params out of the group!
        $this->changeSettingsWithProvisioningProfile($User, $PhoneType);
        return true;
    }

    protected function replaceSettingsWithParameters($params)
    {
        // Logo and Screensaver
        if ($this->mCurrentPhoneModel->supportsLogoDeployment()) {
            // check for custom logo from provisioning profile
            if ($params['logo']) {
                $this->deployFile($params['logo'], "LOGO");
            } else {
                $Phone = $this->getPhoneModel();
                $SipAccount = $Phone->getSipAccount();
                if ($SipAccount) {
                    $this->deployFile("logo_os60_default_light.png", "LOGO");
                } else {
                    $this->deployFile("logo_os60_default_dark.png", "LOGO");
                }
            }
        }

        if ($this->mCurrentPhoneModel->supportsScreenSaverDeployment()) {

            if ($params['screensaver']) {
                $this->deployFile($params['screensaver'], "SCREENSAVER");
            } else {
                $this->deployFile("screensaver_os60.png", "SCREENSAVER");
            }
            $this->psetting("screensaver-enabled", "true");
        }

        $this->psetting($params['name'], $params['value'], $params['meta']);
        Log::d("[" . Yii::app()->session["mac-addr"] . "] Overwriting key from parameter profile: " . $params['name'] . " = " . $params['value'], "siemens-dls");
    }

    private function addXmlPhonebook($mac = '')
    {
        $attributes = array(
            'index' => '1',
            'action' => 'update',
            'display-name' => 'XMLPhonebook',
            'app-name' => 'phonebook',
            'program-name' => "/pb/$mac.xml",
            'control-key' => '2',
            'special-instance' => '2'
        );
        $this->addXmlApp($attributes);
    }

    private function addXmlConfigApp($mac = '')
    {
        $attributes = array(
            'index' => '2',
            'action' => 'update',
            'display-name' => 'XMLConfig',
            'app-name' => 'config',
            'program-name' => "/config/$mac.xml",
            'control-key' => '0',
            'special-instance' => '0'
        );
        $this->addXmlApp($attributes);
    }

    private function addXmlApp($attributes)
    {
        $xmlSettings = array(
            "action" => $attributes['action'],
            "display-name" => $attributes['display-name'],
            "name" => $attributes['app-name'],
            "server-addr" => cfg("PROV_HOST"),
            "server-port" => cfg("PROV_PORT"),
            "transport" => "0",
            "program-name" => $attributes['program-name'],
            "auto-start" => "false",
            "proxy-enabled" => "false",
            "remote-debug" => "false",
            "num-tabs" => "0",
            "all-tabs-start" => "false",
            "restart" => "true",
            "control-key" => $attributes['control-key'],
            "special-instance" => $attributes['special-instance'],
        );
        foreach ($xmlSettings as $settingsKey => $settingsValue) {
            $this->psetting("XML-app-$settingsKey", $settingsValue, $attributes['index']);
        }
    }

    protected function processSoftkeys()
    {
        $Phone = $this->getPhoneModel();
        $SipAccount = $Phone->getSipAccount();
        $User = $SipAccount->getUser();

        $levels = array("fpk", "shift", "ext1", "ext1-shift");
        foreach ($levels as $level) {
            $softKeys = array();
            // $Phone->getCurrentPhoneKeys($User, $level);
            ob_start();
            $softKeys = $Phone->getCurrentPhoneKeys($User, $level);
            $output = ob_get_clean();
            foreach ($softKeys as $softKey) {
                $this->processSoftKey($softKey);
            }
        }
    }

    protected function processSoftKey(PhoneKey $key)
    {
        if ($key->function === 'no') {
            return;
        }

        if ($key->function == "") {
            $key->function = "0";
        }

        $keyFunction = $this->convertSoftKeyFunction($key->function, '58');
        $keyValue = $this->convertSoftKeyValue($key);
        $keyLabel = $key->label;
        $keyName = $key->name;

        $this->psetting("function-key-def", $keyFunction, $keyName);
        $this->psetting("key-label-unicode", $keyLabel, $keyName);

        if ($key->function == "1") {
            $this->psetting('select-dial', $keyValue, $keyName);
        } else if ($key->function == "59") {
            $this->psetting('stimulus-led-control-uri', $keyValue, $keyName);
            $this->psetting('blf-popup', 'true', $keyName);
        } else if ($key->function == "58") { // Feature toggle
            $parts = explode('|', $keyValue);
            if (count($parts) == 3) {
                $this->psetting('stimulus-feature-code', $parts[0], $keyName);
                $this->psetting('stimulus-led-control-uri', $parts[1], $keyName);
                $this->psetting('stimulus-DTMF-sequence', $parts[2], $keyName);
            }
        } else if ($key->function == "X01") { // Feature toggle Callforwarding
            $Phone = $this->getPhoneModel();
            $SipAccount = $Phone->getSipAccount();
            $User = $SipAccount->getUser();

            // Load Callforward for this key and get Target extension
            $attributes = array();
            $attributes["owner"] = $User->id;
            $attributes["key"] = $keyValue;

            if (strpos($keyLabel, '$TARGET') !== false) {
                $presetKey = ForwardPresetPhoneKey::model()->findByAttributes($attributes);
                if ($presetKey != NULL) {
                    $preset = ForwardPreset::model()->findByPk($presetKey->forwardPreset);
                    if ($preset != NULL) {
                        $number = @$preset->getSimpleTargetNumber($User);
                        $label = str_replace('$TARGET', $number, $keyLabel);
                        $this->psetting("key-label-unicode", $label, $keyName);
                    }
                }
            }
            $this->setSoftKeyPsetting($keyFunction, $keyName, $keyValue);
        } else if ($key->function == "X06") {
            $pickupCode = $this->convertPickupCode($key->function, array('59', 'X06'));
            $this->setSoftKeyPsetting($keyFunction, $keyName, $pickupCode . $keyValue);
        } else if (startsWith($key->function, 'X')) {
            $this->setSoftKeyPsetting($keyFunction, $keyName, $keyValue);
        }
    }

    protected function setSoftKeyPsetting($keyFunction, $keyName, $keyValue)
    {
        $this->psetting("function-key-def", $keyFunction, $keyName);
        $this->psetting('stimulus-feature-code', $keyValue, $keyName);
        $this->psetting('stimulus-led-control-uri', $keyValue, $keyName);
        $this->psetting('stimulus-DTMF-sequence', $keyValue, $keyName);
    }

    protected function _getSupportedPhoneModels()
    {
        return Siemens::getSupportedPhoneModels();
    }

    private function getTemplate()
    {
        $filename = dirname(__FILE__) . "/templates/" . $this->mCurrentPhoneModel->getPhoneModelName() . ".xml";

        $data = file_get_contents($filename);
        $xml = new SimpleXMLElement($data);

        foreach ($xml as $section => $element) {
            foreach ($element as $key => $value) {
                $attributes = (array) $value->attributes();
                $this->setting($section, $key, strval($value), "RW", null, @$attributes["@attributes"]);
            }
        }

        return $this->mCurrentSettings;
    }

    private function phonalisaLanguageToSiemensLanguage($lang)
    {
        return substr($lang, 0, 2);
    }
}
