#!/usr/webconfig/bin/php

<?php



class ServerRequest{

    private $args;
    
    public function __construct($args){
        // As we can pass config file as argument all of them are optional
        $this->args = $args;
        if(isset($this->args['config']))
            // If configuration file and other params are passed, those coming
            // from configuration file would be overrided
            $this->args = array_merge($this->fromConfigFile($this->args['config']),$this->args);
    }


    public function __get($key){
        if(($key=='server' || $key=='help') && isset($this->args[$key]))
            return $this->args[$key];
        return null;
    }


    private function parseFile($config){
        if(preg_match('#\.ini$#',$config))
            return parse_ini_file($config);
        return false;
    }
    
    private function fromConfigFile($config){
        if(!stat($config)){
            $this->printMessage(array('status'=>false,'type'=>'local','message'=>"Error: File not found"));
            exit(1);
        }else if(($params = $this->parseFile($config)))
            return $params;
        else{
            $this->printMessage(array('status'=>false,'type'=>'local','message'=>"Error: An error happens during parsing file process"));
            exit(1);
        }
    }

    public function validate(){
        $required = array('name'=>false,
        'description'=>false,
        'venue'=>false,
        'ip'=>true,
        'key'=>true,
        'current'=>true,
        'macid'=>true,
        'altmacid'=>false,
        'mediamacid'=>false,
        'hdserial'=>false,
        'server'=>true
        );

        foreach($required as $key => $mandatory)
            if(!isset($this->args[$key]) && $mandatory)
                return array(false,"Param ".$key." is required");
        return array(true,'');
    }

    public function help(){
        $out = "server-request --ip ipaddress --server <ip:port> --key api-key --current validation-string --macid mac-address [--name] [--description] [--venue] [--altmacid] [--mediamacid] [--hdserial] [--ca] [--help]\n";
        $out.= "server-request --config file.ini\n";
        $out.= "\n  --help        Print this help\n";
        $out.= "  --ip          IP address of the SBC (same IP used for connecting to EMS)\n";
        $out.= "  --server      Server socket where request should be sent\n";
        $out.= "  --key         REST API key\n";
        $out.= "  --current     An identifier used to validate the API call\n";
        $out.= "  --macid       MAC address of the primary ethernet port\n";
        $out.= "  --name        An unique name for the SBC\n";
        $out.= "  --description Description for the particular SBC\n";
        $out.= "  --venue       Information on the location of the SBC\n";
        $out.= "  --altmacid    MAC address of secondary ethernet port, if any\n";
        $out.= "  --mediamacid  MAC Address of media interface\n";
        $out.= "  --hdserial    Serial number of the hard disk\n";
        $out.= "  --ca          PEM file for secure connection (HTTP is used if not present)\n";
        $out.= "  --config      Alternativelly, a config file (.ini) with command line parameters\n";
        $out.= "                Command line parameters override parameters on config file\n";
        return $out;
    }

    public function send(){
        $options = array();
        $hasca = false;
        $server_socket = $this->server;
        if(isset($this->args['ca'])){
            $hasca = true;
            $options[CURLOPT_CAINFO]=$this->args['ca'];
            unset($this->args['ca']);
        }
        if(isset($this->args['current']) && preg_match('#^\{"[^:]+:[^,\}]+[,\}]#',$this->args['current']))
            $this->args['current'] = json_decode($this->args['current'],true);
	else if(isset($this->args['current'])){
	   $this->args['current'] = json_decode(json_encode(array('_id'=>$this->args['current'],'type'=>'admin','parent'=>null),true),true);
	}	
	
        unset($this->args['server']);
        unset($this->args['config']);
        $options = array(
            CURLOPT_RETURNTRANSFER => TRUE,
            CURLOPT_CONNECTTIMEOUT => 5,
            CURLOPT_TIMEOUT => 0,
            CURLOPT_USERAGENT => "SBC - Register",
            // TODO: server path should be passed as parameter also
            CURLOPT_URL => $hasca? "https://".$server_socket."/devicesapi/devices/create" : "http://".$server_socket."/devicesapi/devices/create",
            //                         CURLOPT_CAINFO => self::CACERT_FILE,            
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => json_encode($this->args,true),
            CURLOPT_HTTPHEADER => array('Content-Type: application/json')
        );
        $ch = curl_init();
        curl_setopt_array($ch, $options);
        $data = curl_exec($ch);
        curl_close($ch);
        return @json_decode($data);                
    }

    public function isServerReachable(){
        $port = preg_match('#[^:]+:([0-9]+)$#',$this->server,$match)? $match[1]
            : 80;
        $host = preg_match('#([^:]+)#',$this->server,$match)? $match[1] : null;
        $timeoutInSeconds = 1;
        $ret = false;
        if(($fp = fsockopen($host,$port,$errno,$errstr,$timeoutInSeconds)))
            $ret = true;
        fclose($fp);
        return $ret;
    }

    public static function printMessage($return){
        print json_encode($return);
    }
    
    public static function main($argv){        
        $args = getopt("",array('config:',
        'name:', 
        'description:',
        'venue:',
        'ip:',
        'key:',
        'current:',
        'macid:',
        'altmacid:',
        'mediamacid:',
        'hdserial:',
        'ca:',
        'server:'
        ));

        $request = new ServerRequest($args);
        if(in_array('--help',$argv))
            die($request->help()."\n");
        if((list($status,$message)=$request->validate()) && !$status){
            self::printMessage(array('status'=>false,'type'=>'local','message'=>"Error: ".$message));
            exit(1);
        }else if(!$request->isServerReachable()){
            self::printMessage(array('status'=>false,'type'=>'local','message'=>"Error: Server ".$request->server." is unreachable"));
            exit(1);
        }else if(($response = $request->send()) && ((isset($response->status) && !$response->status) || (!isset($response->status) && !isset($response->id)))){
	   if(isset($response->success) && !$response->success){
	     self::printMessage(array('status'=>false,'type'=>'remote','message'=>$response->message));
	   }else if(!isset($response->success)){
            self::printMessage(array('status'=>false,'type'=>'remote','message'=>(isset($response->description)? "Server Error: ".$response->description :
            "Server Error: Some kind of error happens, but server does not send back any description")));
            }	
            exit(1);
        }else if(!$response){
            self::printMessage(array('status'=>false,'type'=>'remote','message'=>"Error: Connection server error"));
            exit(1);
        }else if($response && isset($response->id))
            self::printMessage(array('status'=>true,'id'=>$response->id,'message'=>"OK: SBC was register on server"));
    }
}

if(php_sapi_name()=='cli')
    ServerRequest::main($argv);

?>
