<?php
require_once __DIR__.'/../modules/provisioningGeneral/phones/ergophone/lib/ErgophoneXml.php';


class ErgophoneCommand extends CConsoleCommand {

    private $ftpRootDirectory = null;
    private $provisioningProfiles = array();
    private $extension=null;
    
    public function run($args)
    {
        
        $params = $this->getParams($args);        
        if ( isset ($params['-ftp']) ) {
            // FIXME get this from config ?? 
            $this->setFtpRootDirectory($params['-ftp']);
        }
        
        if ( isset ($params['-ext']) ) {
            // FIXME get this from config ?? 
            $this->setExtension($params['-ext']);
        }
        
        
        if ($this->ftpRootDirectory != null) {
            $this->createErgophoneConfigPaths();
        }
    }
    
    private function setFtpRootDirectory($dir) {
         $this->ftpRootDirectory = $dir;
    }
    
    private function setExtension($extension) {
        $this->extension = $extension;
    }
    
    
    public function getParams($args) {
        $params = array();
        foreach ($args as $key => $param) {
        
            if (strpos($param,'-') === 0) {
                if (isset($args[($key+1)])) {
                    $params[$param] = $args[($key+1)];
                }
            } 
        
        }
        return $params;
    }
    
    private function createErgophoneConfigPaths() {

        if (is_dir($this->ftpRootDirectory)) {
            $currentDir = $this->ftpRootDirectory;
            if (!is_dir($currentDir.'/EHTIP_0')) {
                mkdir($currentDir.'/EHTIP_0');
            }
            $currentDir.= '/EHTIP_0';
            if (!is_dir($currentDir.'/EH_VOIP')) {
                mkdir($currentDir.'/EH_VOIP');
            }
            $currentDir.= '/EH_VOIP';
            
            if (!$this->extension) {
                $this->createExtensionDirectory("default",$currentDir);
            }
            foreach($this->getPhoneExtensions() as $extension ) {
                $this->createExtensionDirectory($extension,$currentDir);
            }
            
        } else {
        
            echo "Root Directory not found !\n";
        }
    }
    
    private function getPhoneExtensions() {

      if ($this->extension) {
            return array($this->extension);
      }
    
      $users = User::model()->findAll();
      $extensions = array();
      foreach ($users as $user) {
        $extensions[] =$user->extension; 
      } 
      return $extensions;
    }
    
    private function createExtensionDirectory($extension,$currentDir) {

        $currentDir .= "/^".$extension."$";
        if (!is_dir($currentDir)) {
            mkdir($currentDir);
        }
        $this->createXmlConfigFiles($extension, $currentDir);
        $currentDir.="/backup";
        if (!is_dir($currentDir)) {
            mkdir($currentDir);
        }
        $currentDir.="/eventfiles";
        if (!is_dir($currentDir)) {
            mkdir($currentDir);
        }
    }
    
    private function createXmlConfigFiles($extension,$currentDir) {

        $user = User::model()->findByAttributes(array('extension'=>$extension));
        if ($user) {
            
            $group = Groups::model()->findByPk($user->group);
            if ($group->provisioningProfile) {

                if (!array_key_exists($group->provisioningProfile, $this->provisioningProfiles)) {
                    $this->addToProvisioningProfiles($group->provisioningProfile);
                } 
                $this->createPhoneXml($currentDir,$user,$group->provisioningProfile);
            } else {
                $this->createPhoneXml($currentDir,$user);
            }
            
            $this->createVoipXml($currentDir,$user);
            $this->createSystemXml($currentDir,$user);
            $this->createAlertXml($currentDir,$user);
//             echo "created Configs for User : ".$user->name."\n";

        } else {
            $this->createPhoneXml($currentDir);
            $this->createVoipXml($currentDir);
            $this->createSystemXml($currentDir);
            $this->createAlertXml($currentDir);
//             echo "created Default Configs.\n";
        } 
        
    }
    
    private function addToProvisioningProfiles($profileId) {

        $profile = ProvisioningProfile::model()->findByPk($profileId);
         if ($profile) {

            $this->provisioningProfiles[$profileId] = $profile->getParamsForPhone('ergoS501');
         }
    }
    
    

    private function createPhoneXml($currentDir,$user=null,$profileId = null) {
      
        $phoneXmlSettings = array(
            'tonrufmelodie'=>0,
            'tastenklick' => isset($user) ? $user->key_tone :0,
            'phonekontrast'=>5,
            'blitz'=>0,
            'beleuchtung'=>1,
            'bewegungsmelder'=>0,
            'headsetbetrieb'=>0,
            'stoerled'=>0,
            'ausloesezeit'=>0,
            'rufannahme'=>0,
            'funkueberwachung'=>0,
            'anrufled'=>1,
            
//             'sperrart'=>0,
//             'direktrufnummer'=>null,
//             // Max-Anzahl 3
//             'ausnahmenummern' => array(
//                 'ausnahmenummer__1'=>25, // parent name is "ausnahmenummern"
//                 'ausnahmenummer__2'=>24, // parent name is "ausnahmenummern"
//                 'ausnahmenummer__3'=>26, // parent name is "ausnahmenummern"
//             ),

//             'phonepin'=>1111,
//             
//             'rueckmode'=>0,
//             'rueckpin'=>1111,
//             // Wartezeit bis Rufannahme min 10 s max 99 s
//             'wartezeit'=>60,
//             
//             
//             'datum'=>1,
//             'tonrufvolume'=>5,
//             'tonrufmode'=>1,
//             'backuppin'=> 1111,
        // Wartezeit bis Verbindung automatisch getrennt wird min 0 max 9  0 => AUS
        );
     
        if (isset($this->provisioningProfiles[$profileId])) {
            foreach ($this->provisioningProfiles[$profileId] as $param) {           
                if (in_array($param->name,$this->getAllowedPhoneXmlParams())) {
                    $phoneXmlSettings[$param->name] = $param->value;
                }
            } 
        }
        
        
        $xml = new ErgophoneXml('Phone',$currentDir);
        $xml->addItems($phoneXmlSettings);
        $xml->writeXmlFile();
    }
    
    private function getAllowedPhoneXmlParams() {
        return array(
            'tonrufmelodie',
            'phonekontrast',
            'blitz',
            'beleuchtung',
            'bewegungsmelder',
            'headsetbetrieb',
            'stoerled',
            'ausloesezeit',
            'rufannahme',
            'funkueberwachung',
            'anrufled',
            "eigenenummer"
        );
    }
        
        
   //FIXME duplicated code : this comes 1 to 1 from provisioningGeneral/phoneprovisioning
   private 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;
    }
   
        
    private function createVoipXml($currentDir,$user=NULL) {
        
        $useUserSettings = false;
        if ($user) {
            $useUserSettings = true;
            $sipAccount = SipAccounts::model()->findByAttributes(array('user_id'=>$user->id));
        } else {
            //FIXME ! if !sipAccoiunt create new nobody SipAccount
            $sipAccount = SipAccounts::model()->findByAttributes(array('user_id'=>''));
            if ( !$sipAccount ) {
            
                //generate dummy sip account for this phone
                $sipAccount = new SipAccounts();
                $sipAccount->authname = $this->getNextFreeDummyNumber();
                $sipAccount->secret = PasswordGenerator::generateSipPassword();
                $sipAccount->setIsNewRecord(true);
                $sipAccount->save(false);
            }
        }

        $voipSettings = array(
//             'codec_settings' =>array( 
//                 "codec__1"=>array(
//                     'enabled'=>1,
//                     'name'=>"PCMU",
//                     'bit_rate_hi'=>null,
//                     'ptime'=>20,
//                 ),
//                 "codec__2"=>array(
//                     'enabled'=>1,
//                     'name'=>"PCMA",
//                     'bit_rate_hi'=>null,
//                     'ptime'=>20,
//                 ),
//                 "codec__3"=>array(
//                     'enabled'=>1,
//                     'name'=>"G729",
//                     'bit_rate_hi'=>null,
//                     'ptime'=>20,
//                 ),
//                 "codec__4"=>array(
//                     'enabled'=>1,
//                     'name'=>"g723",
//                     'bit_rate_hi'=>null,
//                     'ptime'=>30,
//                 ),
//                 "codec__5"=>array(
//                     'enabled'=>1,
//                     'name'=>"g726-16",
//                     'bit_rate_hi'=>null,
//                     'ptime'=>20,
//                 ),
//                 "codec__6"=>array(
//                     'enabled'=>1,
//                     'name'=>"g726-32",
//                     'bit_rate_hi'=>null,
//                     'ptime'=>20,
//                 ),
//                 "codec__7"=>array(
//                     'enabled'=>1,
//                     'name'=>null,
//                     'bit_rate_hi'=>null,
//                     'ptime'=>0,
//                 ),
//             ),
            'sip'=>array(
//                 'settings'=>array(
//                     'transport_protocol'=>1,  // <!-- 1 = UDP, 2 = TCP -->
//                     'auth_retries'=>4,
//                     'connectMediaOn180'=>0,
//                 ),
                'account'=>array(
                    'enabled'=>1,
                    'id'=> $useUserSettings ? $user->extension : $sipAccount->authname,
                    'name'=>$useUserSettings ? $user->name : "",
                    'auth_name'=>$sipAccount->authname,
                    'auth_password'=>$sipAccount->secret,
                    //<!-- Eigene Rufnummer übertragen? 0 = aus, 1 = ein -->
                    'send_caller_id'=>1, 
                    'registrar' => array(
                        'enabled'=>1,
                        'addr'=>cfg("SIP_HOST"),
                        'port'=>cfg('INTERNAL_SIP_PORT'),
                        'timeout'=>3600,
                    ),
//                     'msgwaiting'=>array(
//                         'enabled'=>0,
//                         'subscribe2mwi'=>1,
//                         'addr'=>null,
//                         'port'=>5060,
//                         'timeout'=>320,
//                     ),
                ),
            ),
//             'dial'=>array(
//                 'timeout'=>5,
//                 'phone_number_max_size'=>20,
//                 'out_of_band_dtmf'=>6, // <!-- 0 = aus, 1 = Inband, 2 = RFC, 3 = Inband+RFC, 4 = SIP, 5 = Inband+SIP, 6 = RFC+SIP -->
//                 'dtmf_payload'=>101,
//                 'media_port'=>4000,
//                 'complete_key'=> array(
//                     'enabled'=>1,
//                     'key'=>'#',
//                 ),
//             ),
//             'sip_info_key_seq'=>array(
//                 'header'=>'text/plain',
//                 'body'=>'FLASH',
//             ),
//             'services'=>array(
//                 'call_waiting'=>array(
//                     'enabled'=>1,
//                 ),
//             ),
        );
        
        $xml = new ErgophoneXml('Voip',$currentDir);
        $xml->addItems($voipSettings);
        $xml->writeXmlFile();
        // make xml from this Settings 
        
    }
    
    private function createSystemXml($currentDir,$user=null) {
        
        $systemSettings = array(
//             'local_ip'=>array(
//                 'addr'=>'192.168.24.133',
//                 'netmask'=>"255.255.255.0",
//                 'domain'=>null,
//             ),
//             'lan_config'=>array(
//                 'lanmode'=>0,
//                 'lanspeed'=>0,
//             ),
//             'dhcp'=>array(
//                 'enabled'=>0,
//             ),
//             'gateway'=>array(
//                 'addr'=>'192.168.100.2',
//             ),
//             'pdu_server'=>array(
//                 'name'=>null,
//                 'addr'=>null,
//                 'txport'=>9999,
//                 'rxport'=>10001,
//             ),
//             'log_server'=>array(
//                 'enabled'=>null,
//                 'addr'=>null,
//                 'port'=>0,
//             ),
//             'ftp_update_tool'=>array(
//                 'auth_name'=>null,
//                 'auth_password'=>null,
//                 // 0 = Nicht nach Updates suchen, 1 = Updates suchen, 2 = Updates suchen und ausführen 
//                 'mode'=>0,
//                 'addr'=>'192.168.100.3',
//                 'port'=>21,
//                 // Alle x Minuten nach Update suchen, wenn mode nicht 0 ist
//                 'interval'=>168,
//                 // Ab welcher Uhrzeit soll nach Updates gesucht werden? 5-stellige Uhrzeit zb: 02:30
//                 'time_begin'=>'00:00',
//                 // Bis welcher Uhrzeit soll nach Updates gesucht werden? 5-stellige Uhrzeit zb: 05:30
//                 'time_end'=>'24:00' ,
//             ),
//             'ftp_config_tool'=>array(
//                 'auth_name'=>null,
//                 'auth_password'=>null,
//                 // Wann bzw. bei welcher Aktion soll die Konfiguration vom Config-Server heruntergeladen werden ? 
//                 // 0 = AUS, 1 = Per Menu, 2 = Beim Karte Stecken, 3 = Beim Karte Ziehen, 4 = Beim Karte Stecken/Ziehen, 5 = Per Intervall
//                 'download_mode'=>0,
//                 // Wann bzw. bei welcher Aktion soll die aktuelle Konfiguration auf den Config-Server hochgeladen werden ?
//                 // 0 = AUS, 1 = Per Menu, 2 = Beim Karte Stecken, 3 = Beim Karte Ziehen, 4 = Beim Karte Stecken/Ziehen, 5 = Nach Speichern, 6 = Per Intervall 
//                 'upload_mode'=>0,
//                 'addr'=>'192.168.100.3',
//                 'port'=>21,
//                 // Alle x Minuten Konfigurationsdateien herunterladen, wenn download_mode nicht 0 ist
//                 'interval'=>24,
//                 // Ab welcher Uhrzeit soll nach Konfigurationsdateien gesucht werden? 5-stellige Uhrzeit zb: 02:30
//                 'time_begin'=>'00:00',
//                 // Bis welcher Uhrzeit soll nach Konfigurationsdateien gesucht werden? 5-stellige Uhrzeit zb: 05:30
//                 'time_end'=>'24:00'
//             ),
             'display_anz'=>array(
//                 // Bitte Wertebereiche 0(=aus) / 1(=ein) beachten
//                 // Symbol während Telefonie-Betrieb anzeigen?
//                 'phone_als_bmp'=>1,
//                 // Symbol während TVR-Betrieb anzeigen?
//                 'tvr_als_bmp'=>1,
//                 // Meldungen als Symbole anzeigen?
//                 'meldungen_als_bmp'=>1,
//                 // http://openbook.galileocomputing.de/c_von_a_bis_z/019_c_zeitroutinen_001.htm#mj0a8102e96a1297bd767ac7274e069f0f
//                 'datum_format'=>null,
//                 //  http://openbook.galileocomputing.de/c_von_a_bis_z/019_c_zeitroutinen_001.htm#mj0a8102e96a1297bd767ac7274e069f0f
                   'zeit_format'=>@$user->extension.' - %H:%M',
             ),
//             'phone_config'=>array(
//                 // Bitte Wertebereiche 0(=aus) / 1(=ein) beachten
//                 // Telefonieren erlaubt?
//                 'telefonerlaubt'=>1,
//                 // Zielwahl nur mit Patientenkarte erlaubt?
//                 'zielwahlnurmitkarte'=>0,
//                 // R-Taste erlaubt?
//                 'rkeyerlaubt'=>0,
//                 // anklopfen erlaubt?
//                 'anklopfen'=>0,
//                 // Wahlwiederholung erlaubt? 0 = nein, 1 = ja; 2 = nur mit Patientenkarte
//                 'wwerlaubt'=>1,
//             ),
//             'bl_led'=>array(
//                 'led_on'=>1,
//             ),
//             'dns_server'=>array(
//                 'addr__1'=>null,
//                 'addr__2'=>null,
//                 'addr__3'=>null,
//             ),
//             'time_server'=>array(
//                 'enabled'=>1,
//                 // Interaval (In Stunden), wann ein Update stattfinden soll
//                 'interval'=>24,             
//                 // Timeout (In Sekunden), wann eine Time-Server Anfrage abgebrochen werden soll
//                 'timeout'=>12,
//                 'time_zone'=>"MEZ-1MESZ-2,M3.5.0/2,M10.5.0/2",
//                 'addr__1'=>"192.168.100.1",
//                 'addr__2'=>null,
//                 'addr__3'=>null,
//             ),
        );
        
        $xml = new ErgophoneXml('System',$currentDir);
        $xml->addItems($systemSettings);
        $xml->writeXmlFile();
    }
    
    // FIXME implement these functions ... 
    private function createAlertXml($currentDir,$user=null) {

        $alarmSettings = array(
            'enabled'=>0,
            'Eventserver'=>array(
                'enabled'=>1,
                'scriptfile'=>"/ergophone.xml",
                'addr'=>cfg('PROV_HOST'),
                'port'=>80,
            ),
        );
        
        
        if ($user) {
            $phoneModel = new Phones();
            $phoneModel->type = "ergoS501";
            $keys = $phoneModel->getCurrentPhoneKeys($user, "");
            $count = count($keys);
            for ($i = 0 ;$i<$count;$i++) {
                $event = $this->getFKeys($keys[$i],$currentDir);
                if ($event != null) {
                    $alarmSettings['Event__'.$i] = $event;
                }
            }
        }
        
        $alarmSettings['Event__connect']['eventid'] = 'Verbundenevent';
        $alarmSettings['Event__connect']['enabled'] = 2;
        $alarmSettings['Event__connect']['eventfile'] = 'pl_connect.xml';
        $this->createEventFile($alarmSettings['Event__connect']['eventfile'],99,$currentDir);
        
        $alarmSettings['Event__disconnect']['eventid'] = 'Aufgelegtevent';
        $alarmSettings['Event__disconnect']['enabled'] = 2;
        $alarmSettings['Event__disconnect']['eventfile'] = 'pl_disconnect.xml';
        $this->createEventFile($alarmSettings['Event__disconnect']['eventfile'],98,$currentDir);
        
        $alarmSettings['Event__poll']['eventid'] = 'CTLpoll';
        $alarmSettings['Event__poll']['enabled'] = 2;
        $alarmSettings['Event__poll']['eventfile'] = 'pl_poll.xml';
        $this->createEventFile($alarmSettings['Event__poll']['eventfile'],97,$currentDir);       
        
        $xml = new ErgophoneXml('Alarm',$currentDir);
        $xml->addItems($alarmSettings);
        $xml->writeXmlFile();
    }
    
    
    private function getFKeys($key,$currentDir) {
        // IMPORTANT Event must start with eventid node !! dont change eventid
        $event = array();
        $event['eventid'] = $key->name;
        $event['identnummer'] = $key->key_idx;
        
        switch ($key->function)
        {
        case 1: // Kurtzwahl
            if ( $key->number_data !== '') {
                $event['enabled'] = 1; // 1 "Anruf"
                $event['eventfile'] = 'Default_Message.xml';
                $event['alarmnummer']= $key->number_data;
                //$event['anzeigetext'] = '';
                return $event;
            } else {
                return null;
            }
        case 2: // Notruf
            if ( $key->number_data !== '') {
                $event['enabled'] = 1; // 1 "Anruf"
//                 $event['eventfile'] = 'Default_Message.xml';
                $event['alarmnummer']= $key->number_data;
                $event['wavefile']= '/var/wav/user/Notruf/de/Notrufansage.wav';
                //$event['anzeigetext'] = '';
                return $event;
            }
//             $this->createEventFile($event['eventfile'],$key->function,$currentDir);
//             return $event;
//         case 3: // licht_aus (test)
//             $event['enabled'] = 2; // 2 "Server"
//             $event['eventfile'] = 'licht_aus.xml';
//             $event['alarmnummer']= $key->number_data;
//             $event['anzeigetext'] = $key->label;
            
//             $this->createEventFile($event['eventfile'],$key->function,$currentDir);
//             return $event;
            
        }
        return null;
    }
    
    private function createEventFile($eventName,$function,$currentDir) {
    
        $eventName = str_replace('.xml','',$eventName);
        $currentDir.="/eventfiles";
        if (!is_dir($currentDir)) {
            mkdir($currentDir);
        }
        $xmlData = array();
        $xmlData['function'] = $function; 
        if ($function == 2) { // 2 = Notruf
            $xmlData['clearevents'] = 'clearevents';
            $xmlData['Notruf'] = 'emergencie';
        }
        
        //  In System.xml eingetragene IP-Adresse
        $xmlData['local_ip'] = 'local_ip'; 
        
        // MAC-Adresse des Gerätes
        $xmlData['macaddress'] = 'macaddress';
        
        // Liefert den Status des Endgerätes 
        // INIT, IDLE, PHONE, TV_RADIO etc.
        $xmlData['ctlstatus'] = 'ctlstatus';
        
        // Eine im Endgerät eingetragene Identnummer,
        // die dem auslösenden Event zugeordnet wurde
        $xmlData['identnummer'] = 'identnummer';
        
        // SIP-ID
        $xmlData['id'] = 'id';
        
        // SIP-Name / Anzeigename
        $xmlData['name'] = 'name';
        
        // Rufnummer der Gegenstelle
        // $xmlData['extern'] = 'extern';
        
        
        /*
            DTMF-String welcher von der verbundenen Gegenstelle empfangen wurde.
            Die DTMF-Zeichen werden nicht einzeln, sondern in einer Zeichenkette
            übertragen. Die Länge der Zeichenkette nimmt mit jedem DTMF-Zeichen um
            eins zu.
            
            $xmlData['dtmf'] = 'dtmf';
        */
        
        /*
            Status ob es sich um ein eingehendes oder ausgehendes Gespräch handelt.
            IN = Eingehendes Gespräch, OUT = Ausgehendes Gespräch
            UNKNOWN = Status nicht verfügbar bzw. unbekannt

            $xmlData['origin'] = 'origin';
        */

        $xml = new ErgophoneXml($eventName,$currentDir);
        $xml->addItems($xmlData);
        $xml->writeXmlFile();
    }
    
}
?>
