<?php

require_once 'StringHelper.php';

//require_once 'PhoneModelFactory.php' ;

class VirtualPhoneProvisioningController
{

    const LOG_TAG = '';

    protected $mController = null;
    protected $mManufactorName = null;
    protected $mMacAddress = null;
    protected $mIPv4Address = null;
    protected $mCurrentPhoneModel = null;
    protected $mCurrentFirmwareVersion = null;
    protected $mCurrentRequesterInformations = null;
    protected $mCurrentUserInformations = null;
    protected $mCurrentSettings = array();
    protected $mCurrentProvisioningJob = NULL;
    protected $mCurrentRealPhoneModelInstance = NULL;
    protected $mPhonalisaProvisioningVariables = array();

    protected function getProvURL($mac = null)
    {
        $protocol = cfg('PROV_PROTOCOL');
        $host = cfg('PROV_HOST');
        $port = cfg('PROV_PORT');
        $prov = cfg('PROV_BASEPATH');

        if ($port != '') {
            $port = ":" . $port;
        }

        //fix for tiptel 3130 check if this works with other phones
        if ($mac) {
            if (substr($mac, 0, 6) == '000CC4') {
                return $protocol . $host . $port . $prov . $mac . '.cfg';
            }
        }
        return $protocol . $host . $port . $prov;
    }

    public static function getXmlAppPhonebookInstanceForPhoneModel($mac, $ua)
    {
        $upperMac = strtoupper($mac);
        $lowerUA = strtolower($ua);
        switch (substr($upperMac, 0, 6)) {
            case "001565":
            case "805EC0":
            case "805E0C":  //This is Tiptel 2xx
                require_once dirname(__FILE__) . '/../phones/tiptel-2xx/xmlapps/XmlPhonebookApp.php';
                break;
            case "001AE8":  //This is Siemens
                require_once dirname(__FILE__) . '/../phones/siemens/xmlapps/XmlPhonebookApp.php';
                break;
            case "000413":  //This is SNOM
                require_once dirname(__FILE__) . '/../phones/snom/xmlapps/XmlPhonebookApp.php';
                break;
            case "000CC4":
            case "001FC1":
                if (startsWith($lowerUA, 'tiptel 32')) {
                    require_once dirname(__FILE__) . '/../phones/tiptel-32xx/xmlapps/XmlPhonebookApp.php';
                } else if (startsWith($lowerUA, 'tiptel t31') || startsWith($lowerUA, 'tiptel 31')) {
                    require_once dirname(__FILE__) . '/../phones/tiptel-31xx/xmlapps/XmlPhonebookApp.php';
                } else {
                    require_once dirname(__FILE__) . '/../phones/tiptel-30xx/xmlapps/XmlPhonebookApp.php';
                }
                break;
            case "7C2F80":
            case "589EC6":  //This is Gigaset
                require_once dirname(__FILE__) . '/../phones/gigaset/xmlapps/XmlPhonebookApp.php';
                break;
            default:
                throw new CHttpException(501, 'Not Implemented');
        }
        $app = new XmlPhonebookApp();
        $app->mMacAddress = $mac;
        return $app;
    }

    public static function getXmlAppPhoneConfigInstanceForPhoneModel($mac, $ua)
    {
        $upperMac = strtoupper($mac);
        $lowerUA = strtolower($ua);
        switch (substr($upperMac, 0, 6)) {
            case "001565":
            case "805EC0":
            case "805E0C":  //This is Tiptel 2xx
                require_once dirname(__FILE__) . '/../phones/tiptel-2xx/xmlapps/XmlPhoneConfigApp.php';
                break;
            case "001AE8":  //This is Siemens
                require_once dirname(__FILE__) . '/../phones/siemens/xmlapps/XmlPhoneConfigApp.php';
                break;
            case "000413":  //This is SNOM
                require_once dirname(__FILE__) . '/../phones/snom/xmlapps/XmlPhoneConfigApp.php';
                break;
            case "000CC4":
            case "001FC1":
                if (startsWith($lowerUA, 'tiptel 32')) {
                    require_once dirname(__FILE__) . '/../phones/tiptel-32xx/xmlapps/XmlPhoneConfigApp.php';
                } else if (startsWith($lowerUA, 'tiptel t31') || startsWith($lowerUA, 'tiptel 31')) {
                    require_once dirname(__FILE__) . '/../phones/tiptel-31xx/xmlapps/XmlPhoneConfigApp.php';
                } else {
                    require_once dirname(__FILE__) . '/../phones/tiptel-30xx/xmlapps/XmlPhoneConfigApp.php';
                }
                break;
            default:
                throw new CHttpException(501, 'Not Implemented');
        }
        $app = new XmlPhoneConfigApp();
        $app->mMacAddress = $mac;
        return $app;
    }

    public static function getXmlLoginAppInstanceForPhone($mac, $ua)
    {
        $upperMac = strtoupper($mac);
        $lowerUA = strtolower($ua);
        switch (substr($upperMac, 0, 6)) {
            case "001565":
            case "805EC0":
            case "805E0C":  //This is Tiptel 2xx
                require_once dirname(__FILE__) . '/../phones/tiptel-2xx/xmlapps/XmlPhoneLoginApp.php';
                break;
            case "000413":  //This is SNOM
                require_once dirname(__FILE__) . '/../phones/snom/xmlapps/XmlPhoneLoginApp.php';
                break;
            case "000CC4":
            case "001FC1":
                if (startsWith($lowerUA, 'tiptel 32')) {
                    require_once dirname(__FILE__) . '/../phones/tiptel-32xx/xmlapps/XmlPhoneLoginApp.php';
                } else if (startsWith($lowerUA, 'tiptel t31') || startsWith($lowerUA, 'tiptel 31')) {
                    require_once dirname(__FILE__) . '/../phones/tiptel-31xx/xmlapps/XmlPhoneLoginApp.php';
                } else {
                    require_once dirname(__FILE__) . '/../phones/tiptel-30xx/xmlapps/XmlPhoneLoginApp.php';
                }
                break;
            default:
                throw new CHttpException(501, 'Not Implemented');
        }
        $app = new XmlPhoneLoginApp();
        $app->mMacAddress = $mac;
        return $app;
    }

    public static function getXmlAppVoicemailInstanceForPhoneModel($mac, $ua)
    {
        $upperMac = strtoupper($mac);
        $lowerUA = strtolower($ua);
        switch (substr($upperMac, 0, 6)) {
            case "001565":
            case "805EC0":
            case "805E0C":  //This is Tiptel 2xx
                require_once dirname(__FILE__) . '/../phones/tiptel-2xx/xmlapps/XmlVoicemailApp.php';
                break;
            case "000CC4":
            case "001FC1":
                if (startsWith($lowerUA, 'tiptel 32')) {
                    require_once dirname(__FILE__) . '/../phones/tiptel-32xx/xmlapps/XmlVoicemailApp.php';
                } else if (startsWith($lowerUA, 'tiptel t31') || startsWith($lowerUA, 'tiptel 31')) {
                    require_once dirname(__FILE__) . '/../phones/tiptel-31xx/xmlapps/XmlVoicemailApp.php';
                } else {
                    require_once dirname(__FILE__) . '/../phones/tiptel-30xx/xmlapps/XmlVoicemailApp.php';
                }
                break;
            default:
                throw new CHttpException(501, 'Not Implemented');
        }
        $app = new XmlVoicemailApp();
        $app->mMacAddress = $mac;
        return $app;
    }

    public static function getInstanceForPhoneModel($mac, $ua)
    {
        if (startsWith($mac, "y0000000000")) { //FIXME this is not supported at the moment.
            die();
        }
        $upperMac = strtoupper($mac);
        $lowerUA = strtolower($ua);
        switch (substr($upperMac, 0, 6)) {
            case "001565":
            case "805EC0":
            case "805E0C":  //This is tiptel/yealink
                if (startsWith($ua, "Yealink SIP-T4") || startsWith($ua, "Yealink SIP-T5") || startsWith($ua, "Yealink SIP-T23P") || startsWith($ua, "Yealink SIP-CP")) { // FIXME Make dynamic!
                    require_once dirname(__FILE__) . '/../phones/yealink-t4x/provisioning.php';
                    return new YealinkT4XPhoneProvisioning();
                }
                require_once dirname(__FILE__) . '/../phones/tiptel-2xx/provisioning.php';
                return new TiptelPhoneProvisioning();
            case "000413":  //This is SNOM
                require_once dirname(__FILE__) . '/../phones/snom/provisioning.php';
                return new SnomPhoneProvisioning();
            case "001AE8":  //This is Siemens
                require_once dirname(__FILE__) . '/../phones/siemens/provisioning.php';
                return new SiemensPhoneProvisioning();
            case "000B82":  //This is Grandstream
                require_once dirname(__FILE__) . '/../phones/grandstream/provisioning.php';
                return new GrandstreamPhoneProvisioning();
            case "000CC4":  //This is Tiptel 3xx
                $lowerUA = str_replace("tiptel tiptel", "tiptel", $lowerUA);
                if (startsWith($lowerUA, 'tiptel 32')) {
                    require_once dirname(__FILE__) . '/../phones/tiptel-32xx/provisioning.php';
                    return new TiptelPhoneProvisioning();
                } else if (startsWith($lowerUA, 'tiptel t31') || startsWith($lowerUA, 'tiptel 31')) {
                    require_once dirname(__FILE__) . '/../phones/tiptel-31xx/provisioning.php';
                    return new TiptelPhoneProvisioning();
                } else if (startsWith($lowerUA, 'tiptel 33')) {
                    require_once dirname(__FILE__) . '/../phones/tiptel-33xx/provisioning.php';
                    return new Tiptel33xxPhoneProvisioning();
                } else {
                    require_once dirname(__FILE__) . '/../phones/tiptel-30xx/provisioning.php';
                    return new TiptelPhoneProvisioning();
                }
            case "001FC1":  //This is Htek
                require_once dirname(__FILE__) . '/../phones/htek/provisioning.php';
                return new HtekPhoneProvisioning();
            case "7C2F80":
            case "589EC6": //This is Gigaset
                require_once dirname(__FILE__) . '/../phones/gigaset/provisioning.php';
                return new GigasetPhoneProvisioning();
            default:
                throw new CHttpException(501, 'Not Implemented');
        }
    }

    public function getPhoneModel()
    {
        $phone = $this->mCurrentRealPhoneModelInstance;

        if ($phone == NULL) {
            $phone = Phones::model()->findByAttributes(array("mac_addr" => $this->mMacAddress));

            if ($phone == NULL) {
                //this is a new Phone
                $phone = $this->generateNewPhone();
            } else {
                $phone->type = $this->mCurrentPhoneModel->getPhoneModelName();
                $phone->firmware = $this->mCurrentFirmwareVersion;
                $phone->ipv4_address = $this->mIPv4Address;
                if (!$phone->save()) {
                    dump($phone->errors);
                }
            }
            $this->mCurrentRealPhoneModelInstance = $phone;
        }
        return $phone;
    }

    protected function getNextFreeDummyNumber()
    {
        $dummy_prefix = "95"; ///FIXME: Query configuration for this
        $new_found = false;
        $max_tries = 10000;
        do {
            // generate random SipAccount 95XXXXX
            $dummy = $dummy_prefix . PasswordGenerator::generatePassword(5, "0123456789");
            //check if this dummy exists
            $model = SipAccounts::model()->findByAttributes(array("authname" => $dummy));
            if (!$model) {
                $new_found = true;
            }
            --$max_tries;
            if ($max_tries == 0) {
                //write an fatal error...
                break;
            }
        } while (!$new_found);
        return $dummy;
    }

    protected function generateNewPhone()
    {
        $model = new Phones();
        $model->mac_addr = $this->mMacAddress;
        $model->type = $this->mCurrentPhoneModel->getPhoneModelName();
        $model->nobody_index = 1;
        $model->added = 1;
        $model->firmware = $this->mCurrentFirmwareVersion;
        $model->fw_manual_update = 0;
        $model->ipv4_address = $this->mIPv4Address;
        $model->setIsNewRecord(true);

        //generate dummy sip account for this phone
        $sipaccount = new SipAccounts();
        $sipaccount->authname = $this->getNextFreeDummyNumber();
        $sipaccount->secret = PasswordGenerator::generateSipPassword();
        $sipaccount->setIsNewRecord(true);

        $sipaccount->save(false);

        $model->sip_account_id = $sipaccount->id;
        $model->nobody_index = $sipaccount->id;

        if (!$model->save(false)) {

            foreach ($model->errors as $errors) {
                foreach ($errors as $key => $value)
                    Log::d("$key => $value", "ergotest");
            }
        }
        return $model;
    }

    protected function setProvisioningJobStarted()
    {
        // is there any Prov job for this Phone?
        if (isset($this->mCurrentRealPhoneModelInstance->id)) {
            $attributes = array();
            $attributes["phone_id"] = $this->mCurrentRealPhoneModelInstance->id;
            $attributes["status"] = Job::Triggered;
            $attributes["type"] = Job::Provisioning;
            $this->mCurrentProvisioningJob = Job::model()->findByAttributes($attributes);
        }

        if ($this->mCurrentProvisioningJob != NULL) {
            $this->mCurrentProvisioningJob->status = Job::Running;
            $this->mCurrentProvisioningJob->save();
        }
    }

    protected function setProvisioningJobNeedToTriggerAgain()
    {
        if ($this->mCurrentProvisioningJob != NULL) {
            $this->mCurrentProvisioningJob->status = Job::NeedToTriggerAgain;
            $this->mCurrentProvisioningJob->save();
        }
    }

    protected function setProvisioningJobFinished()
    {
        if ($this->mCurrentProvisioningJob != NULL) {
            //$this->mCurrentProvisioningJob->status = Job::Finished;
            $this->mCurrentProvisioningJob->delete();
        }
    }

    protected function runFirmwareUpdate(Firmware $fwUpdate)
    {
        Log::w("[" . $this->mMacAddress . "] Firmware update is not supported for this Phone model.", "phonalisa-dls");
        return true;
    }

    protected function checkForFirmwareUpdate()
    {
        // get current firmware version
        if ($this->mCurrentFirmwareVersion == "") {
            Log::w("[" . $this->mMacAddress . "] Could not check Firmware Version (Phone has not reported one!).", "phonalisa-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 . ").", "phonalisa-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.", "phonalisa-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("[" . $this->mMacAddress . "] No Firmware-file is available and set to standard for Phone.", "phonalisa-dls");
                return false;
            }
            $firmware = $firmwares[0];
            if ($firmware->version == $this->mCurrentFirmwareVersion) {
                Log::v("[" . $this->mMacAddress . "] Firmware on Phone (" . $this->mCurrentFirmwareVersion . " is the same as the standard Firmware (" . $firmware->version . ").", "phonalisa-dls");
                return false;
            }

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

    public function run($controller)
    {
        $mController = $controller;

        $mac = Yii::app()->request->getParam("mac");

        //$ua  = "Tiptel IP 386 38.0.13.4 00:15:65:1e:67:6a";//
        $ua = Yii::app()->request->getUserAgent();

        if (!$this->checkIfEnabled()) {
            throw new CHttpException(404, 'Provisioning System not enabled.');
        }

        if (!$this->checkIfRequesterIsAllowedInNetwork()) {
            throw new CHttpException(403, 'not allowed to request settings.');
        }

        if (!$this->checkMacAddress($mac)) {
            throw new CHttpException(403, 'not allowed to request settings.');
        }

        if (!$this->checkUserAgent($ua)) {
            throw new CHttpException(403, 'not allowed to request settings.');
        }

        $this->getPhoneModel();
        $this->setProvisioningJobStarted();
        $this->changeExpireTimeIfExpireRangeChanged();

        $fwUpdate = $this->checkForFirmwareUpdate();
        $getSettings = true;
        if ($fwUpdate !== false) {
            $getSettings = $this->runFirmwareUpdate($fwUpdate);
        }
        $this->setPhonalisaProvisioningVariables();
        if ($getSettings == true) {
            $this->loadConfigValues($mac);
        }
        $this->setProvisioningJobFinished();
        $this->setLastProvTimestampToPhonesModel();
        //$this->renderPartial('index');
        //FIXME: Move this to the view!
        ob_start();

        $this->generateOutput();
        header('Expires: 0');
        header('Pragma: no-cache');
        header('Cache-Control: private, no-cache, must-revalidate');
        header('Content-Type: text/plain; charset=utf-8');
        header('Vary: *');
        header('Content-Length: ' . (int) @ob_get_length());
        @ob_flush();
        //$this->render('index');
    }

    protected function setLastProvTimestampToPhonesModel()
    {
        $mac = $this->mMacAddress;
        if (!$mac && !empty(Yii::app()->session["mac-addr"])) {
            $mac = str_replace(":", "", Yii::app()->session["mac-addr"]);
        }

        $phone = Phones::model()->findByAttributes(array("mac_addr" => $mac));
        if (!$phone) {
            return;
        }

        if (isset($phone->last_prov_timestamp)) {
            $phone->last_prov_timestamp = PhonalisaDate::newServerTimestamp();
        }
        if (isset($phone->last_prov_dateTime)) {
            $phone->last_prov_dateTime = PhonalisaDate::newServerDate();
        }
        $phone->save();
    }

    protected function checkIfEnabled()
    {
        //FIXME: get phone manufactor name and check if this settings is enabled
        return true;
    }

    protected function checkIfRequesterIsAllowedInNetwork()
    {
        //FIXME: get phone manufactor name and check if this net is allowed
        // Save IP
        $this->mIPv4Address = $_SERVER['REMOTE_ADDR'];
        return true;
    }

    protected function checkMacAddress($mac)
    {
        $this->mMacAddress = $mac;
        return true;
    }

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

    protected function loadConfigValues($mac = null)
    {
        return true;
    }

    protected function generateOutput()
    {
        return false;
    }

    protected function setCurrentFirmwareVersion($fw)
    {
        $this->mCurrentFirmwareVersion = $fw;
    }

    protected function setCurrentMacAddress($mac)
    {
        $this->mMacAddress = $mac;
    }

    protected function setCurrentPhoneModel(AbstractPhoneModel $model)
    {
        $this->mCurrentPhoneModel = $model;
    }

    public function getManufactorName()
    {
        return $this->mManufactorName;
    }

    public function getProvisioningProfiles($User)
    {
        $provisioningProfile = array();
        if ($User) {
            $provisioningProfile = $User->getRevelantProvisioningProfiles();
        } else if (cfg("DUMMY_PROV_PROFILE")) {
            $provisioningProfile[] = $this->getDummyProvisioningProfile(cfg("DUMMY_PROV_PROFILE"));
        }
        return $provisioningProfile;
    }

    public function getDummyProvisioningProfile($profileID)
    {
        return ProvisioningProfile::model()->findByPk($profileID);
    }

    public function convertLanguageCode($code)
    {
        $codes = array();
        $codes["de_de"] = "German";
        $codes["en_us"] = "English";
        $codes["fr_fr"] = "French";

        if (array_key_exists($code, $codes)) {
            return $codes[$code];
        }
        return "English";
    }

    public function changeExpireTimeIfExpireRangeChanged()
    {
        $Phone = $this->getPhoneModel();
        $SipAccount = $Phone->getSipAccount();
        if (!$SipAccount) {
            return;
        }
        $currentExpire = $SipAccount->expires;

        $configExpireTime = cfg('STANDARD_EXPIRE_TIME');
        $configExpireTimePool = explode('-', $configExpireTime);
        if (!empty($configExpireTimePool[1])) {
            $expireStartTime = trim($configExpireTimePool[0]);
            $expireEndTime = trim($configExpireTimePool[1]);
            if (!(($expireStartTime <= $currentExpire) && ($currentExpire <= $expireEndTime))) {
                $SipAccount->scenario = 'expireRangeChange';
            }
        } else if ($currentExpire !== $configExpireTime) {
            $SipAccount->scenario = 'expireRangeChange';
        }

        if ($SipAccount->scenario == 'expireRangeChange') {
            $SipAccount->save();
        }
    }

    public function setPhonalisaProvisioningVariables()
    {
        $this->mPhonalisaProvisioningVariables = array(
            '%PROV_PROTOCOL%' => cfg('PROV_PROTOCOL'),
            '%PROV_HOST%' => cfg('PROV_HOST'),
            '%PROV_PORT%' => cfg('PROV_PORT'),
            '%PROV_PORT_SECURE%' => cfg('PROV_PORT_SECURE'),
            '%PROV_BASEPATH%' => cfg('PROV_BASEPATH'),
            '%PROV_URL%' => $this->getProvURL(),
            '%SIP_HOST%' => cfg('SIP_HOST'),
            '%INTERNAL_SIP_PORT%' => cfg('INTERNAL_SIP_PORT'),
            '%EXTERNAL_SIP_PORT%' => cfg('EXTERNAL_SIP_PORT'),
            '%INTERNAL_TLS_PORT%' => cfg('INTERNAL_TLS_PORT'),
            '%EXTERNAL_TLS_PORT%' => cfg('EXTERNAL_TLS_PORT'),
        );


        $phoneModel = $this->getPhoneModel();
        if ($phoneModel) {
            $this->mPhonalisaProvisioningVariables['%MAC%'] = $phoneModel->mac_addr;
            $this->setSIPAccountSpecificProvisioningVariables($phoneModel->sip_account_id);
        }
    }

    protected function setSIPAccountSpecificProvisioningVariables($sipAccountID)
    {
        $sipAccount = SipAccounts::model()->findByPk($sipAccountID);
        if ($sipAccount) {
            $this->mPhonalisaProvisioningVariables['%PHONE_LABEL%'] = $sipAccount->getLabel();
            $this->mPhonalisaProvisioningVariables['%SIP_AUTHNAME%'] = $sipAccount->authname;
            $this->setUserSpecificProvisioningVariables($sipAccount->user_id);
        }
    }

    protected function setUserSpecificProvisioningVariables($userID)
    {
        $user = User::model()->findByPk($userID);
        if ($user) {
            $this->mPhonalisaProvisioningVariables['%USER_EXTENSION%'] = $user->extension;
            $this->mPhonalisaProvisioningVariables['%USER_NAME%'] = $user->name;
            $this->mPhonalisaProvisioningVariables['%USER_FIRSTNAME%'] = $user->firstname;
            $this->mPhonalisaProvisioningVariables['%USER_LASTNAME%'] = $user->lastname;
        }
    }

    protected function convertSoftKeyValue($key)
    {
        $keyFunction = $key->function;
        $keyValue = $key->number_data;
        $userExtension = $this->getUserExtension();
        switch ($keyFunction) {
            case 'X01': //Call Forward
                $keyValue = cfg('DP_FWD_ON_PREFIX') . $keyValue . '*' . $userExtension;
                break;
            case 'X02': // Night Circuit
                $keyValue = "*89*" . $keyValue; //FIXME: add cfg-key if available
                break;
            case 'X03': // Queue Login/Logout
                $keyValue = "*5" . $keyValue . '*' . $userExtension; //FIXME: add cfg-key if available
                break;
            case 'X04': // SpeedDial
                $keyValue = cfg('DP_SPEED_DIAL_ON_PREFIX') . $keyValue;
                break;
            case 'X05': // Voicemail
                $keyValue = cfg('DP_VOICEMAIL_LISTENING_PREFIX');
                break;
            case 'X06': // Direct Pickup
                $keyValue = $keyValue;
                break;
            case 'X07': // Intercom
                $keyValue = '*85*' . $keyValue; //FIXME: add cfg-key if available
                break;
            case 'X08': // DND
                $keyValue = cfg('DP_DND_ON_PREFIX') . $userExtension;
                break;
            case 'X09': // Group Listening
                $keyValue = cfg('DP_EAVESDROP_PREFIX') . $keyValue;
                break;
            case 'X10': // Logout from all Queues
                $keyValue = "*5*"; //FIXME: add cfg-key if available
                break;
            case 'X11': // Hot Desking
                $keyValue = cfg('DP_MOBILIY_PREFIX') . $keyValue;
                break;
            case 'X12': // Login to all Queues
                $keyValue = "*5"; //FIXME: add cfg-key if available
                break;
            case 'X13': // Call Group Login/Logout
                $keyValue = "*6" . $keyValue . '*' . $userExtension; //FIXME: add cfg-key if available
                break;
        }
        return $keyValue;
    }

    protected function getUserExtension()
    {
        $Phone = $this->getPhoneModel();
        $SipAccount = $Phone->getSipAccount();
        $User = $SipAccount->getUser();
        if ($User == NULL) {
            return $SipAccount->authname;
        }
        return $User->extension;
    }

    protected function convertPickupCode($keyFunction, $attributes, $pickupCode = '')
    {
        if (in_array($keyFunction, $attributes)) {
            $pickupCode = cfg('DP_PICKUP_PREFIX');
        }
        return $pickupCode;
    }

    protected function convertSoftKeyFunction($keyFunction, $blfKey)
    {
        if (startsWith($keyFunction, 'X')) {
            $keyFunction = $blfKey;
        }
        return $keyFunction;
    }

    protected function changeSettingsWithProvisioningProfile($user, $phoneType)
    {
        $provisioningProfiles = $this->getProvisioningProfiles($user);
        $provVariableKeys = array_keys($this->mPhonalisaProvisioningVariables);
        $provVariables = $this->mPhonalisaProvisioningVariables;
        foreach ($provisioningProfiles as $provisioningProfile) {
            foreach ($provisioningProfile->getParamsForPhone($phoneType) as $param) {
                $parameterList = array();
                $parameterList['name'] = $param->name;
                $parameterList['value'] = str_replace($provVariableKeys, $provVariables, $param->value);
                $parameterList['meta'] = $param->meta;
                $parameterList['logo'] = $this->getImageName($provisioningProfile, $phoneType, 'logo');
                $parameterList['screensaver'] = $this->getImageName($provisioningProfile, $phoneType, 'screensaver');

                $this->replaceSettingsWithParameters($parameterList);
            }
        }
    }

    private function getImageName($provisioningProfile, $phoneType, $key)
    {
        $imageName = $provisioningProfile->valueForKey($phoneType . "_" . $key, '');
        if ($imageName) {
            $imageName = $phoneType . "_" . $key . "_" . $imageName . ".png";
        }
        return $imageName;
    }

    protected function replaceSettingsWithParameters($params)
    {
        $this->psetting($params['name'], $params['value']);
        Log::d("[$this->mMacAddress] Overwriting key from parameter profile: " . $params['name'] . " = " . $params['value'], self::LOG_TAG);
    }
}
