<?php
namespace App;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Session;

class Vms {
    
    var $password; 
    var $port;
    var $host;

    var $fp = null ;

    var $iRetryCurrentNumber = 0 ;
    var $iRetryMaxNumber = 100 ;

    function __construct()
    {
		$this->host = config('vms.host');  //  "127.0.0.1";
		$this->port = config('vms.port'); //  "8021";
		$this->password = config('vms.password');// "mteam";

		return $this ;
		
    }

    private function event_socket_create() {
        try {
            $this->fp = fsockopen($this->host, $this->port, $errno, $errdesc);
        } catch (Exception $e) {
           
        }
        

        if (!$this->fp) {
            if( $this->iRetryCurrentNumber < $this->iRetryMaxNumber ){
                $this->iRetryCurrentNumber++ ;
                sleep(1);
                return $this->event_socket_create() ;
            }else{
                die("Connection to $this->host failed");  
            }            
        }
            
        $this->iRetryCurrentNumber = 0 ;
        socket_set_blocking($this->fp,false);

        if ($this->fp) {
            while (!feof($this->fp)) {
                $buffer = fgets($this->fp, 1024);
                usleep(100); //allow time for reponse
                if (trim($buffer) == "Content-Type: auth/request") {
                    fputs($this->fp, "auth $this->password\n\n");
                    break;
                }
            }
            return $this->fp;

        }else {
            return false;
        }           
    }

    public function event_socket_close() {
        $this->fp->close();
    }


    public function eRequest( $cmd ) {

        if( is_null( $this->fp )  ){
            $this->event_socket_create();
        }
    
        if ($this->fp) {   
			//var_dump($cmd);
            fputs($this->fp, $cmd."\n\n");    
            usleep(100); //allow time for response

            $response = '';
            $length = 0;
            $x = 0;
            while (!feof($this->fp) )
            {
                $x++;
                usleep(10);
                $theNewData = stream_get_line($this->fp, 4096, "\n");
				
                if ($length > 0) {
                    $response .= $theNewData . "\n";
                }

                if ($length == 0 && strpos($theNewData, 'Content-Length:') !== false) {
                    $length = (int)str_replace('Content-Length: ', '', $theNewData);
                }

                if ($length > 0 && strlen($response) >= $length) {
                    break;
                }

                if ($x > 10000) break;
            }
            $this->fp = null;
			
			
			
            // If a JSON response, process the event, otherwise return the raw result

            if ((strpos($response, '{') === 0) || (substr($response, 0,2) == '[{')) {

                $response = $this->getJsonReponseClean( $response ) ;
                if( is_array( $response )){
                    $myFSEvent = new FreeSwitchEvent();
                    $myFSEvent = $myFSEvent->loadFromArray( $response ) ;

                    $this->SendFreeSwitchEvent( $myFSEvent );
                }
            }else{

                return $response;
            }

        }else {
            echo "no handle";
        }
    }

    /*
    * Send FreeSwitchEvent to ...
    */
    private function SendFreeSwitchEvent( $_FreeSwitchEvent  ){

        if( !is_null( $_FreeSwitchEvent ) ){

            var_dump( $_FreeSwitchEvent ) ;

        }
       
       return true ;
    }

	public function isConfStreaming($r){
		$arConf = $this->getConferenceArray($r);
		$stream = false;
		
		if( empty($arConf["members"]) ){ return false; }
		
		foreach( $arConf["members"] as $mbr ){
			if(!empty($mbr["type"])){
				if( $mbr["type"] == 'recording_node' ){
					if( substr($mbr["record_path"],0,4) == 'rtmp' ){
						$stream = true;
					}
				}
			}
		}
		
		return $stream;
	}
	
    public function getConferenceArray($r){
		$response = $this->eRequest( "api conference ".$r." json_list" );

		if( substr($response,0,4) == "-ERR" ) { return "Server error"; }
		if( empty($response)) { return "Server response is empty";}
		
		$arRespArRooms = json_decode($response."}]",true);
		return $arRespArRooms[0];
	}
	
    public function getConfNumberInfos($i){
		if( empty($i["room"]) ){ return array("result"=>"error", "msg"=>"No room"); }

		$arRespArRooms = $this->getConferenceArray($i["room"]);
		
		$mmbrs = 0;
		if( empty($arRespArRooms["members"]) ){ return array("result"=>"error", "msg"=>"No room"); }
		
		foreach( $arRespArRooms["members"] as $mbr ){
			if(!empty($mbr["caller_id_name"])){
				if( $mbr["caller_id_name"] != "Admin"){
					$mmbrs++;
				}
			}
				//"conference_name"
		}
		return array(
			"conference" => $arRespArRooms["conference_name"],
			"mcount" => $mmbrs,
			"conference_uuid" => $arRespArRooms["conference_uuid"],
			"msgs" => 10,
		);
	}
	
    public function getAllWssUsers(){
	
		$usResponse = $this->eRequest( "api verto status" );
		
		$arUsLines = explode("\n",$usResponse);
		$arUsers = array();
		$uCols = array();
		foreach( $arUsLines as $users  ){
			$arVals = preg_match("/::(\d{3,})\@\d{1,2}.*?(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}):\d{3,5}/",$users,$matches);
			//var_dump( $matches );
			if( !empty($matches) ){
				$arUsers[$matches[1]] = $matches;
			}
			//$arLine = explode(" ",$users);
			//if($arLine[""])
		}
	return $arUsers;
	}
	
    public function getChannelsInfo($room=false){
		$usResponse = $this->eRequest( "api show channels" );
		
		$arUsLines = explode("\n",$usResponse);
		
		$arChannels = array();
		$uCols = array();
		foreach( $arUsLines as $chans  ){
			$arLine = explode(",",$chans);
			if( count($arLine) > 1 ){
				if( $arLine[0] == "uuid"){
					foreach( $arLine as $cl ){
						$uCols[] = $cl;
					}
				} else {
					$nChan = array();
					foreach( $arLine as $uKey=>$uLine ){
						$nChan[$uCols[$uKey]] = $uLine;
					}
					if( (!empty($room)) && ($nChan["dest"] != $room) && ( $nChan["application_data"] != $room) ) { continue; }
					$arChannels[$nChan["uuid"]] = $nChan;
				}
			}
		}
		return $arChannels;
	}
	
    public function getOnlineUsers(){
		$usResponse = $this->eRequest( "api show registrations" );
		
		$arUsLines = explode("\n",$usResponse);
		
		$arOnlines = array();
		$uCols = array();
		foreach( $arUsLines as $users  ){
			if( strlen($users) < 20 ){ continue; }
			$arLine = explode(",",$users);
			if( $arLine[0] == "reg_user"){
				foreach( $arLine as $cl ){
					$uCols[] = $cl;
				}
			} else {
				$nUser = array();
				foreach( $arLine as $uKey=>$uLine ){
					$nUser[$uCols[$uKey]] = $uLine;
				}
				$arOnlines[$nUser["reg_user"]] = $nUser;
			}
		}
		
		return $arOnlines;
	}
	
    public function getAllUsersByRooms(){
		
		
		
		$usResponse = $this->getAllUsers();
		
		$rUsrs = array();
		
		foreach($usResponse as $usr) { 
			$rUsrs[$usr["callgroup"]][] = $usr;
		}
		
		return $rUsrs;
		
	}	
    public function getOneUserInfo($num){
		if(empty($num)){
			return false;
		}
		$arsUser = DB::table('clients')->where('number', $num)->get();
		if(empty($arsUser)){
			return false;
		}
		$arUser = json_decode(json_encode($arsUser[0]),true);
		
		$users_path = config('vms.users_path');
		
		if( !file_exists( $users_path ."vmj_".$num.".xml") ){
			return false;
		}
		$arXmlFileUser = $this->XML2JSON( $users_path."vmj_".$num.".xml" );
		if(empty($arXmlFileUser)){ 
			return false; 
		}
		$arUser["peer"] = self::getUserDataFromXML($arXmlFileUser);
		
		return $arUser;
	}
	
    public function getAllUsers($room=false){
		//$arWssUsers = $this->getAllWssUsers();
		$dbUsers = DB::select('select * from clients');
		$ardbUsers = array();
		$ardbLoginUsers = array();
		foreach($dbUsers as $dbusr){ $ardbUsers[] = $dbusr->number; $ardbLoginUsers[$dbusr->number] = $dbusr; } //->login
		
		$usResponse = $this->eRequest( "api list_users" );
		
		$arUsLines = explode("\n",$usResponse);
		
		$arUsers = array();
		$uCols = array();
		foreach( $arUsLines as $users  ){
			$arLine = explode("|",$users);
			if( count($arLine) > 1 ){
				if( $arLine[0] == "userid"){
					foreach( $arLine as $cl ){
						$uCols[] = $cl;
					}
				} else {
					$nUser = array();
					foreach( $arLine as $uKey=>$uLine ){
						
						/*if( !empty($arWssUsers[1]) ){
							if($arWssUsers[1] == $uLine["userid"]){
								$uLine["contact"] = "wss://".$arWssUsers[2];
							}
						}*/
						$nUser[$uCols[$uKey]] = $uLine;
					}
					if(!empty($room)) { if( $nUser["callgroup"] != $room) { continue; }}
					if($nUser["userid"]=="default") {  continue; }
					
					if( in_array($nUser["userid"],$ardbUsers) ){
						$nUser["peertype"]='webrtc';
					} else {
						$nUser["peertype"]='sip';
					}
					
					if( !empty($ardbLoginUsers[$nUser["userid"]]) ){
						$nUser["login"]=$ardbLoginUsers[$nUser["userid"]]->login;
						$nUser["name"]=$ardbLoginUsers[$nUser["userid"]]->name;
						$nUser["bandwidth_in"]=$ardbLoginUsers[$nUser["userid"]]->bandwidth_in;
						$nUser["bandwidth_out"]=$ardbLoginUsers[$nUser["userid"]]->bandwidth_out;
					} else {
						$nUser["name"]= (!empty($nUser["effective_caller_id_name"])) ? $nUser["effective_caller_id_name"] : "SomeOne"; 
					}
					
					$arUsers[$nUser["userid"]] = $nUser;
				}
			}
		}
		

		return $arUsers;
		
	}
	
    public function getOneRoom($r){
		$rPath = config('vms.rooms_path');
		$room_file = $rPath . "vmj_" . $r . ".xml";
		$arRoom = $this->XML2JSON( $room_file );
		if(!$arRoom){ return false;}
		return $this->getRoomData($arRoom);
	}
	
    public function getActiveItemData($d){
		if( (empty($d['room']) )){ return "No Room";}
		
		if( $d['lid']>-1 ){ $lid = $d['lid']; } else { return "No Layer id"; }
		
		$response = $this->eRequest( "api conference " . $d["room"] . " json_list");
		if( substr($response,0,4) == "-ERR" ) { return "Server error"; }
		if( empty($response)) { return "Server response is empty";}
		
		$arRespArRooms = json_decode($response."}]",true);
		$arRespArRoom = $arRespArRooms[0];
		
		foreach( $arRespArRoom["members"] as $mbr ){
			if( isset($mbr["video_layer_id"]) ){
				if( $mbr["video_layer_id"] == $lid ){
					return $mbr;
				}
			}
		}
		return "No found Layer id - ".$lid;
	}
	
    public function getActiveRoomData($room){
		if( empty( $room )) { return []; }
		$response = $this->eRequest( "api conference ".$room." json_list" );
		if( substr($response,0,4) == "-ERR" ) { return []; }
		if( empty($response)) { return [];}
		
		$arRespArRooms = json_decode($response."}]",true);
		
		$arRespArRoom = $arRespArRooms[0];
		
		$arChans = $this->getChannelsInfo($room);
		$arOnlineSips = $this->getOnlineUsers();
		$arRoomUsers = $this->getAllUsers($room);
		$arRoomAllUsers = [];
		$arRoomOFFUsers = [];
		$arRoomVideoUsers = [];
		$arRoomVoiceUsers = [];
		
		$arRespArRoom["members_old"] = $arRespArRoom["members"];
		if(!empty($arRespArRoom["members"])){
			foreach( $arRespArRoom["members"] as $mKey => $mmbrs ){
				
				if( $mmbrs["type"] == "recording_node"){
					if( substr($mmbrs["record_path"],-6) == "stream" ){
						$arRespArRoom["streaming"] = $mmbrs;
					} else {
						$arRespArRoom["recordings"] = $mmbrs;
					}
					unset($arRespArRoom["members"][$mKey]);
					continue;
				}
				
				if(empty($mmbrs["uuid"])){
					unset($arRespArRoom["members"][$mKey]);
					continue;
				}
				
				if(($mmbrs["caller_id_name"] == "Admin")){
						unset($arRespArRoom["members"][$mKey]);
						continue;
				}		
				
				/*if( isset($mmbrs["video_layer_id"]) ){
					if(($mmbrs["video_layer_id"] == "-1") && $mmbrs["flags"]["hold"] == false){
						unset($arRespArRoom["members"][$mKey]);
						continue;
					}
				}*/

				if( (!empty($arChans[$mmbrs["uuid"]])) ){
					/*if( $mmbrs["caller_id_name"] == "Outbound Call" ){
						$mmbrs["caller_id_name"] = $arRoomUsers[$mmbrs["caller_id_number"]]["effective_caller_id_name"];
					}
					$arRespArRoom["members"][$mKey]["fullname"] = $mmbrs["caller_id_name"];
					$arRespArRoom["members"][$mKey]["more"] = $arChans[$mmbrs["uuid"]];
					
					$mmbrs["fullname"] = $mmbrs["caller_id_name"];
					$mmbrs["more"] = $arChans[$mmbrs["uuid"]];
					*/
					unset($arRoomUsers[$mmbrs["caller_id_number"]]);
				}

				if( ($mmbrs["video_layer_id"] == "-1") && ($mmbrs["flags"]["hold"] == false) ){
					if( $mmbrs["caller_id_name"] == "Outbound Call" ){
						$mmbrs["caller_id_name"] = $arRoomUsers[$mmbrs["caller_id_number"]]["effective_caller_id_name"];
					}
					
					$mmbrs["caller_id_name"] = '<i class="fa fa-microphone"></i> '.$mmbrs["caller_id_name"];
					$mmbrs["calltype"] = 'audio';
					$mmbrs["fullname"] = $mmbrs["caller_id_name"];
					if( !empty($arChans[$mmbrs["uuid"]]) ){
						$mmbrs["more"] = $arChans[$mmbrs["uuid"]];
					}
					
					
					$arRoomVoiceUsers[] = $mmbrs;
					unset($arRespArRoom["members"][$mKey]);
					continue;
				} else {
					if( $mmbrs["caller_id_name"] == "Outbound Call" ){
						if(!empty($arRoomUsers[$mmbrs["caller_id_number"]])){
							$mmbrs["caller_id_name"] = $arRoomUsers[$mmbrs["caller_id_number"]]["effective_caller_id_name"];
						}
					}
					
					$mmbrs["caller_id_name"] = '<i class="fa fa-video-camera"></i> '.$mmbrs["caller_id_name"];
					$mmbrs["calltype"] = 'video';
					$mmbrs["fullname"] = $mmbrs["caller_id_name"];
					$mmbrs["more"] = ( !empty($arChans[$mmbrs["uuid"]]) ) ? $arChans[$mmbrs["uuid"]] : [];
					
					
					$arRoomVideoUsers[] = $mmbrs;
					unset($arRespArRoom["members"][$mKey]);
					continue;
				}
				
			}
		} else {
			$arRespArRoom["conference"] = 'offline';
			
		}
		
		foreach( $arRoomUsers as $uKey=>$usr ){
			if( !empty($arOnlineSips[$usr["userid"]]) ){
				$usr["network_ip"] = $arOnlineSips[$usr["userid"]]["network_ip"];
				$usr["network_port"] = $arOnlineSips[$usr["userid"]]["network_port"];
				$arRoomAllUsers[] = $usr;
			} else {
				$arRoomOFFUsers[] = $usr;
			}
				
			/**if( substr($usr["contact"],0,5) == "error" ){
				
				$arRoomOFFUsers[] = $usr;
			} else {
				 // $arRoomUsers
				unset($arRoomUsers[$uKey]);
			} */
		}
		
		$arRoomAllUsers = array_merge_recursive($arRoomAllUsers,$arRoomOFFUsers);
		
		
		$arRespArRoom["members"] = array_merge_recursive($arRoomVideoUsers,$arRoomVoiceUsers);
		
		$roomData = $this->getOneRoom($room);
		$roomProfile = $this->getOneProfile( $roomData["profile"] );
		
		//$room_currlayout_name = (!empty($arRespArRoom["current_video_layout_name"])) ? $arRespArRoom["current_video_layout_name"] : "";
		$room_currlayout_name = (!empty($arRespArRoom["canvases"][0]["vlayout_name"])) ? $arRespArRoom["canvases"][0]["vlayout_name"] : "";
		
		$room_layout_name = ((empty($room_currlayout_name))&&(!empty($roomProfile["video-layout-name"]))) ? $roomProfile["video-layout-name"] : $room_currlayout_name;
		$roomLayout = $this->get_one_layout( $room_layout_name );
		//$roomLayout = $this->get_one_layout( $roomProfile["video-layout-name"] );
		$arRespArRoom["data"] = $roomData;
		$arRespArRoom["profile"] = $roomProfile;
		$arRespArRoom["video-layout"] = $roomLayout;
		$arRespArRoom["channels"] = $arChans; //$arRoomUsers;
		$arRespArRoom["offline_members"] = $arRoomAllUsers; //$arRoomUsers;
		//$recs_path = $rPath = config('vms.records_path');
		return $arRespArRoom;
	}
	
    public function list_recordings($i){
		if( empty($i["room"]) ){ return ""; }
		$room = $i["room"];
		$recs_path = $rPath = config('vms.records_path');
		$files = array_diff(scandir($recs_path), array('.', '..'));
		if( empty($files) ) {return "";}
		$elems = array();
		foreach( $files as $recf ){
			$rl = strlen($room);
			if( substr($recf,0,$rl) == $room ){
				$elems[] = array("filename"=>$recf, "size"=>filesize($recs_path.$recf));
			}
		}
		
		return $elems;
	}
	
	public function getUserPass($i){
		if( empty($i["number"]) ) { return false; }
		$num = $i["number"];
		$users_path = config('vms.users_path');
		if( file_exists($users_path."vmj_".$num.".xml") ){
			
			$arUser = $this->XML2JSON( $users_path."vmj_".$num.".xml" );
			if(empty($arUser)){ return false; }
			$elR = self::getUserDataFromXML($arUser);
			if( !empty($elR["password"]) ){
				return $elR["password"];
			}
		} else {
			return false;
		}
	}
	
    public function removeUser($num){
		$users_path = config('vms.users_path');
		if( file_exists($users_path."vmj_".$num.".xml") ){
			unlink( $users_path."vmj_".$num.".xml" );
			$response = $this->eRequest( "api reloadxml" );
			DB::table('clients')->where('number',$num)->delete();
			return "ok";
		}
		return $num." - file is not found. (".$users_path."vmj_".$num.".xml)";
	}
	
    public function changeProfileLayout($i){
		if( (empty($i["room"])) || (empty($i["layout"]))){ return array("result"=>"error","msg"=>"Layout or Room is empty");}
		
		$arRoom = $this->getOneRoom($i["room"]);
		
		return array("result"=>"ok","msg"=>$arRoom);
		
		if( !empty($arRoom["conference"])){
			//$arProf = getOneProfile($pr)
			//$prof_path = config('vms.profiles_path');
		}
	}
	
    public function getOneProfile($pr){
		$prof_path = config('vms.profiles_path');
		if( file_exists($prof_path."vmj_".$pr.".xml") ){
			$arProfile = $this->XML2JSON( $prof_path."vmj_".$pr.".xml" );
			if(empty($arProfile)){ return false; }
			return $this->getProfileData($arProfile);
		} else {
			return false;
		}
	}
	
    public function getAllProfiles(){
		
		$prof_path = config('vms.profiles_path');
		
		$files = array_diff(scandir($prof_path), array('.', '..'));
		if( empty($files) ) {return "";}
		$elems = array();
		foreach( $files as $xmlf ){
			$arProfile = $this->XML2JSON( $prof_path.$xmlf );
			//var_dump($arProfile);
			if(!$arProfile){ continue; }
			$elR = $this->getProfileData($arProfile);
			$elems[$elR["name"]] = $elR;
		}
		return $elems;
	}
	
    public function getNewRoomNumberByMinMax($min,$max){  
		
		$rPath = config('vms.rooms_path');
		$files = array_diff(scandir($rPath), array('.', '..'));
		if( empty($files) ) {return "";}
		$elems = array();
		foreach( $files as $xmlf ){
			
			$arRoom = $this->XML2JSON( $rPath.$xmlf );
			if(!$arRoom){ continue; }
			$elR = $this->getRoomData($arRoom);
			if( ($elR["number"]>=$min) && ($elR["number"]<=$max) ){
				$elems[$elR["number"]] = $elR["number"];
			}
		}
		$lastNum = max(array_keys($elems));
		return $lastNum + 1;
	}
    public function getAllRoomsArray(){  
		
		$rPath = config('vms.rooms_path');
		$files = array_diff(scandir($rPath), array('.', '..'));
		if( empty($files) ) {return "";}
		$elems = array();
		foreach( $files as $xmlf ){
			
			$arRoom = $this->XML2JSON( $rPath.$xmlf );
			if(!$arRoom){ continue; }
			$elR = $this->getRoomData($arRoom);
			$elems[$elR["number"]] = $elR["number"];
		}
		return $elems;
	}
    public function getAllRooms(){  
		$rPath = config('vms.rooms_path');
		
		$arDbRooms = collect(DB::table('rooms')->get())->keyBy('number');
		// TODO TO DO DOING
		
		//$arUsrs = $this->getAllUsersByRooms();
		$arUsrs = $this->getAllUsers();
		
		$files = array_diff(scandir($rPath), array('.', '..'));
		if( empty($files) ) {return "";}
		$elems = array();
		foreach( $files as $xmlf ){
			
			$arRoom = $this->XML2JSON( $rPath.$xmlf );
			if(!$arRoom){ continue; }
			$elR = $this->getRoomData($arRoom);

			$arRoomUserNums = (!empty($arDbRooms[$elR["number"]]->users) ) ? json_decode($arDbRooms[$elR["number"]]->users) : [];

			$roomUsers = [];
			$roomUserNames = [];
			foreach($arRoomUserNums as $rnm ){
				if( !empty($arUsrs[$rnm]) ){
					$roomUsers[] = $arUsrs[$rnm];
					$roomUserNames[$rnm] = $arUsrs[$rnm]["name"];
				}
			}
			$elR["userscount"] = (!empty($arRoomUserNums)) ? count($arRoomUserNums) : 0;
			$elR["users"] = (!empty($arDbRooms[$elR["number"]])) ? implode(",",$arRoomUserNums) : 0;
			$elR["usernames"] = $roomUserNames;
			$elR["arusers"] = $roomUsers ;
			$elems[$elR["number"]] = $elR;
		}
		return $elems;
	}
	
	public function getAllActiveRooms(){
		// Get Rooms Statuses in System
		
		$response = $this->eRequest( "api conference json_list" );
		
		if( empty($response)) { return "";}
		
		$arRespRooms = json_decode($response."}]",true);
		
		
		
		$arActiveRooms = array();
		foreach( $arRespRooms as $aRoom ){
			$arActiveRooms[$aRoom["conference_name"]] = $aRoom;
		}
		
		return $arActiveRooms;
	}
	
	public static function getUserDataFromXML($arUser){
		$r = array();
		$r["number"] = $arUser["user"]["id"];
		foreach( $arUser["user"]["params"]["param"] as $prs ){
			if( $prs["name"] == "password" ){
				$r["password"] = $prs["value"];
			}
		}
		
		foreach( $arUser["user"]["variables"]["variable"] as $vars ){
			if( $vars["name"] == "callgroup" ){
				$r["room"] = $vars["value"];
			}
			if( $vars["name"] == "effective_caller_id_name" ){
				$r["name"] = $vars["value"];
			}
		}
		
		return $r;
	}
	
	
	public function getProfileData($arProf){
		$p = array();
		$p["name"] = $arProf["name"];
				
		foreach ( $arProf["param"] as $prm ){
			
			if( !empty($prm["name"]) ){
				$p[$prm["name"]] = $prm["value"];
			}
		}
		return $p;
	}
		
	public static function getRoomData($arRoom){
		
		$r = array();
		$r["name"] = $arRoom["extension"]["name"];
		$numPregs = preg_match("/[0-9]{1,}/",$arRoom["extension"]["condition"]["expression"],$nummatch);
		$r["number"] = $nummatch[0]; //substr($arRoom["extension"]["condition"]["expression"],1,-1);
		
		foreach ( $arRoom["extension"]["condition"]["action"] as $a ){
			//var_dump($a);
			if( !empty($a["data"]) ){
				if( substr($a["data"],0,17) == "video_banner_text" ){
					$tSts = substr($a["data"],18);
					
					$arBr = explode("}",$tSts);
					$arBanner = explode(",",substr($arBr[0],1));
					
					$r["subtitle_text"] = $arBr[1];
					$r["subtitle"] = array();
					foreach( $arBanner as $bv ){
						$arb = explode("=",$bv);
						$r["subtitle"][$arb[0]] = $arb[1]; 
					}
				}
				if( $a["application"] == "conference" ){
					$r["profile"] = substr($a["data"],7);
				}
				if( substr($a["data"],0,23) == "conference_member_flags" ){
					$r["member_flags"] = substr($a["data"],24);
				}
			}
		}
		return $r;
	}
	
    private static function getActiveRooms(){ 
		//conference json_list
	}
	
	/*
		Metod: Save or create USER
		
		Usage: saveUser([num,password,name,<room>])
	*/
	public function saveUser($arPeer){
		/*
			num
			password
			name
			room
		*/
		if( empty($arPeer["num"]) || empty($arPeer["password"]) || empty($arPeer["name"])){
			return false;
		}
		
		if( $arPeer["nopass"] ){
			$uPass = $arPeer["password"]; 
		}
		elseif( !empty($arPeer["typeuser"]) ) { 
			if($arPeer["typeuser"]=="webrtc") {
				$webrtc = true;
				$uPass = md5($arPeer["password"]);
			} else {
				$uPass = $arPeer["password"]; 
			}
		} else {
			$uPass = $arPeer["password"]; 
		}
		
		if( empty($arPeer["room"]) ) { $pRoom = '7777';} else { $pRoom = $arPeer["room"]; }
		$db_bandwidth_in = '';
		$db_bandwidth_out = '';
		if( !empty($arPeer["ptzurl"]) ) { $ptzurl = $arPeer["ptzurl"];} else { $ptzurl = ""; }
		if( !empty($arPeer["bandwidth_in"]) ) { $db_bandwidth_in = $arPeer["bandwidth_in"]; $bandwidth_in = '<variable name="rtp_video_max_bandwidth_in" value="'.$arPeer["bandwidth_in"].'kb"/>';} else { $bandwidth_in = ""; }
		if( !empty($arPeer["bandwidth_out"]) ) { $db_bandwidth_out = $arPeer["bandwidth_out"]; $bandwidth_out = '<variable name="rtp_video_max_bandwidth_out" value="'.$arPeer["bandwidth_out"].'kb"/>';} else { $bandwidth_out = ""; }
		/*
		<variable name="rtp_video_max_bandwidth_in" value="20kb"/>
        <variable name="rtp_video_max_bandwidth_out" value="20kb"/>

		*/
		$peer_temp = '<include>
		  <user id="'.$arPeer["num"].'">
			<params>
			  <param name="password" value="'.$uPass.'"/>
			  <param name="vm-password" value="'.$uPass.'"/>
			</params>
			<variables>
			  '.$bandwidth_in .'
			  '.$bandwidth_out .'
			  <variable name="toll_allow" value="domestic,international,local"/>
			  <variable name="accountcode" value="'.$arPeer["num"].'"/>
			  <variable name="user_context" value="default"/>
			  <variable name="effective_caller_id_name" value="'.$arPeer["name"].'"/>
			  <variable name="effective_caller_id_number" value="'.$arPeer["num"].'"/>
			  <variable name="outbound_caller_id_name" value="'.$arPeer["name"].'"/>
			  <variable name="outbound_caller_id_number" value="'.$arPeer["num"].'"/>
			  <variable name="callgroup" value="'.$pRoom.'"/>
			  <variable name="ptzurl" value="'.$ptzurl.'"/>
			</variables>
		  </user>
		</include>';

		
		if( $this->save_user_file($arPeer["num"], $peer_temp) ){

			$response = $this->eRequest( "api reloadxml" );
			
			if($arPeer["typeuser"]=="webrtc"){
				
				$jsonRoomUsers = DB::table('rooms')->where('number', $pRoom)->value('users');
				if(!empty($jsonRoomUsers)){
					$arRoomUsers = json_decode($jsonRoomUsers);
					if(empty($arRoomUsers[$arPeer["num"]])){
						$arRoomUsers[] = $arPeer["num"];
						$rusrEditData['users'] = json_encode( $arRoomUsers );
						DB::table('rooms')->where('number', $pRoom)->update($rusrEditData);
					}
				}
				
				$params_Save_User = [
					'number' => $arPeer["num"], 
					'login' => $arPeer["login"],
					'password' => $uPass,
					'name' => $arPeer["name"],
					'bandwidth_in' => $db_bandwidth_in,
					'bandwidth_out' => $db_bandwidth_out,
					'typeuser' => $arPeer["typeuser"],
					//'room' =>$pRoom
				];
						
				$myuid = DB::table('clients')->where('number', $arPeer["num"])->value('id');
				if(!empty($myuid)){
					$updans = DB::table('clients')->where('id', $myuid)->update($params_Save_User);
					$anstype = 'upd';
				} else {
					$uid = DB::table('clients')->insertGetId($params_Save_User);
					$anstype = 'ins';
				}
			}
			
			$arPeer["prms"] = $params_Save_User;
			$arPeer["type"] = $anstype;
			return $arPeer;
		}
	}
	
    public function saveRoom( $r ){
		/*
			saveRoom( 
				number | 7777
				name | vMajlis
				member_flags | join-vid-floor
				conf_profile | 'video-mcu-stereo'
			)
		*/
		if( empty($r["number"]) || empty($r["name"]) ) { return "Room name is empty"; }
		if( empty($r["name"])) { $r["name"] = 'vMajlis-'.random_int(1234, 8899); } 
		if( empty($r["conf_profile"]) ){ $r["conf_profile"] = 'vmj_default_profile'; } //video-mcu-stereo
		$room_xml = $this->createRoomXml( $r );
		
		if( $this->save_room_file($r["number"], $room_xml) ){
			if( !empty($r["roomusers"])) { 
				//rooms 
				/*
				id	int(10) unsigned Автоматическое приращение	
				name	varchar(255)	
				number	varchar(10)
				profile	varchar(100)
				users	text	
				desc	text	
				pin	varchar(255)	
				layout	varchar(255)	
				created_at	timestamp [0000-00-00 00:00:00]	
				updated_at	timestamp [0000-00-00 00:00:00]
				*/
				$roomData = [
					'name' => $r["name"], 
					'number' => $r["number"], 
					'users' => (!empty($r["roomusers"])) ? json_encode($r["roomusers"]) : "",
					'profile' => (!empty($r["conf_profile"])) ? $r["conf_profile"] : "",
					'desc' => (!empty($r["desc"])) ? $r["desc"] : "",
					'pin' => (!empty($r["pin"])) ? $r["pin"] : "",
					'layout' => (!empty($r["layout"])) ? $r["layout"] : "",
					];
				
				$rid = DB::table('rooms')->where('number', $r['number'])->value('id');
				if( !empty($rid) ){
					DB::table('rooms')->where('id', $rid)->update($roomData);
					$retAns = $rid."_Upd";
				} else {
					$rid = DB::table('rooms')->insertGetId($roomData);
					$retAns = $rid."_Ins";
				}
			}
			return "ok";
		} else {
			return "File not saved";
		}
	}
	public function generateRandomString($length = 10) {
        $characters = '_0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $charactersLength = strlen($characters);
        $randomString = '';
        for ($i = 0; $i < $length; $i++) {
            $randomString .= $characters[rand(0, $charactersLength - 1)];
        }
        return $randomString;
    }
    private static function createRoomXml( $r ){
		/*
			//profile | cdquality_stereo_conferences
			number | 7777
			name | vMajlis
			member_flags | join-vid-floor
			
		*/
		if( empty($r["number"]) || empty($r["name"]) ) { return false; }
		
		if( !empty($r["member_flags"])) { $member_flags = "\t\t\t".'<action application="set" data="conference_member_flags='.$r["member_flags"].'"/>'."\n"; } else { $member_flags = ''; }
		if( !empty($r["conf_profile"])) { $conf_profile = $r["conf_profile"]; } else { $conf_profile = 'vmj_default_profile'; } //video-mcu-stereo
		if( !empty($r["conference_controls"])) { $conference_controls = "\t\t\t".$r["conference_controls"]."\n"; } else { $conference_controls = ''; }
		return '<include>'."\n".
			"\t".'<extension name="'.$r["name"].'">'."\n".
				"\t\t".'<condition field="destination_number" expression="^('.$r["number"].')(\d)$">'."\n".
					"\t\t\t".'<action application="jitterbuffer" data="50"/>'."\n".
					"\t\t\t".'<action application="export" data="nolocal:jitterbuffer_msec=50"/>'."\n".
					"\t\t\t".'<action application="set" data="rtp_jitter_buffer_plc=true"/>'."\n".
					"\t\t\t".'<action application="answer"/>'."\n".
					"\t\t\t".'<action application="send_display" data="'.$r["name"].'|$1"/>'."\n".
					"\t\t\t".'<action application="set" data="video_mute_png=/usr/local/freeswitch/vmajlis_images/video-mute.png"/>'."\n".
                    "\t\t\t".'<action application="system" data="php /usr/local/freeswitch/conf/scripts/make_png_text.php \'${caller_id_name}\' \'/tmp/${caller_id_name}.png\' \'1920\' \'1080\'"/>'."\n".
                    "\t\t\t".'<action application="set" data="video_logo_path={position=center-bot}/tmp/${caller_id_name}.png"/>'."\n".
					$member_flags.
					$conference_controls.
					"\t\t\t".'<action application="conference" data="$1@'.$conf_profile.'+flags{moderator}"/>'."\n".
				"\t\t".'</condition>'."\n".
			"\t".'</extension>'."\n".
		'</include>';
		/*
		<condition field="destination_number" expression="^(7777)(\d)?$">
                        <action application="log" data="$1-$2"/>
                        <action application="jitterbuffer" data="50"/>
                        <action application="export" data="nolocal:jitterbuffer_msec=50"/>
                        <action application="set" data="rtp_jitter_buffer_plc=true"/>
                        <action application="answer"/>
                        <action application="send_display" data="Technounit-GROUP|$1"/>
                        <!--action application="set" data="rtp_video_max_bandwidth_in=512kb"/-->
                        <!--action application="set" data="rtp_video_max_bandwidth_out=512kb"/-->
                        <action application="set" data="video_mute_png=/usr/local/freeswitch/vmajlis_images/video-mute.png"/>
                        <action application="system" data="php /usr/local/freeswitch/conf/scripts/make_png_text.php '${caller_id_name}' '/tmp/${caller_id_name}.png' '1920' '1080'"/>
                        <action application="set" data="video_logo_path={position=center-bot}/tmp/${caller_id_name}.png"/>
                        <action application="conference" data="$1@vmj_default_profile+flags{moderator}"/>
                </condition>

		*/
		
	}




	/*
		Metod: Save or create PROFILE
		
		Usage: saveUser([num,password,name,<room>])
	*/
	public function saveLayout($arLayout){
		if( (empty($arLayout["name"])) || (empty($arLayout["blocks"])) ){ return false; }
		if( !is_array($arLayout["blocks"]) ) {	return false; }
		
		$lName = preg_replace('/[^a-zA-Z0-9]/', '', $arLayout["name"]);
		
		if( empty($lName) ) { return false; }
		
		$auto_3d_position = ( !empty($arProf["auto-3d-position"]) ) ? $arProf["auto-3d-position"] : "false";
		
		$layout_temp = '<layout name="$lName" auto-3d-position="'.$auto_3d_position.'">
                <image x="0" y="0" scale="144" floor="true"/>
                <image x="144" y="0" scale="144"/>
                <image x="288" y="0" scale="72"/>
                <image x="288" y="72" scale="72"/>
                <image x="288" y="144" scale="72"/>
                <image x="0" y="216" scale="72"/>
                <image x="72" y="216" scale="72"/>
                <image x="144" y="216" scale="72"/>
                <image x="216" y="216" scale="72"/>
                <image x="288" y="216" scale="72"/>
                <image x="0" y="288" scale="72"/>
                <image x="72" y="288" scale="72"/>
                <image x="144" y="288" scale="72"/>
                <image x="216" y="288" scale="72"/>
                <image x="288" y="288" scale="72"/>
        </layout>';
		
		if( $this->save_layout_file($lName, $peer_temp) ){
			
			$response = $this->eRequest( "api reloadxml" );
			return "ok";
		}
	}

	/*
		Metod: Save or create PROFILE
		
		Usage: saveUser([num,password,name,<room>])
	*/
	public function saveProfile($arProf){
		/*
			name
			video-layout-name (2top+15)
			video-canvas-size (1920x1080)
			video-canvas-bgcolor (#333333)
			video-layout-bgcolor (#000000)
			video-codec-bandwidth (2mb)
			video-fps (30)
			
			<!-- <param name="tts-engine" value="flite"/> -->
			<!-- <param name="tts-voice" value="kal16"/> -->
		*/
		
		if( empty($arProf["name"]) ){	return "Name is empty";	}
		
		$pName = preg_replace('/[^a-zA-Z]/', '', $arProf["name"]);
		
		if( empty($pName) ) { return "Name is empty"; }
		
		$video_layout_name = ( !empty($arProf["video-layout-name"]) ) ? $arProf["video-layout-name"] : "2top+15";
		$video_canvas_size = ( !empty($arProf["video-canvas-size"]) ) ? $arProf["video-canvas-size"] : "1280x720";
		$video_canvas_bgcolor = ( !empty($arProf["video-canvas-bgcolor"]) ) ? $arProf["video-canvas-bgcolor"] : "#333333";
		$video_layout_bgcolor = ( !empty($arProf["video-layout-bgcolor"]) ) ? $arProf["video-layout-bgcolor"] : "#000000";
		$video_codec_bandwidth = ( !empty($arProf["video-codec-bandwidth"]) ) ? $arProf["video-codec-bandwidth"] : "2mb";
		$video_fps = ( !empty($arProf["video-fps"]) ) ? $arProf["video-fps"] : "30";
		
		
		$peer_temp = '<profile name="'.$pName.'">
				<param name="domain" value="$${domain}"/>
				<param name="rate" value="48000"/>
				<param name="channels" value="2"/>
				<param name="interval" value="20"/>
				<param name="energy-level" value="200"/>
				<param name="muted-sound" value="conference/conf-muted.wav"/>
				<param name="unmuted-sound" value="conference/conf-unmuted.wav"/>
				<param name="alone-sound" value="conference/conf-alone.wav"/>
				<param name="moh-sound" value="$${hold_music}"/>
				<param name="enter-sound" value="tone_stream://%(200,0,500,600,700)"/>
				<param name="exit-sound" value="tone_stream://%(500,0,300,200,100,50,25)"/>
				<param name="kicked-sound" value="conference/conf-kicked.wav"/>
				<param name="locked-sound" value="conference/conf-locked.wav"/>
				<param name="is-locked-sound" value="conference/conf-is-locked.wav"/>
				<param name="is-unlocked-sound" value="conference/conf-is-unlocked.wav"/>
				<param name="pin-sound" value="conference/conf-pin.wav"/>
				<param name="bad-pin-sound" value="conference/conf-bad-pin.wav"/>
				<param name="caller-id-name" value="$${outbound_caller_name}"/>
				<param name="caller-id-number" value="$${outbound_caller_id}"/>
				<param name="comfort-noise" value="false"/>
				<param name="conference-flags" value="video-floor-only|rfc-4579|livearray-sync|minimize-video-encoding"/>
				<param name="video-mode" value="mux"/>
				<param name="video-layout-name" value="'.$video_layout_name.'"/>
				<param name="video-canvas-size" value="'.$video_canvas_size.'"/>
				<param name="video-canvas-bgcolor" value="'.$video_canvas_bgcolor.'"/>
				<param name="video-layout-bgcolor" value="'.$video_layout_bgcolor.'"/>
				<param name="video-codec-bandwidth" value="'.$video_codec_bandwidth.'"/>
				<param name="video-fps" value="'.$video_fps.'"/>
			</profile>';
		if( $this->save_profile_file($pName, $peer_temp) ){
			
			$response = $this->eRequest( "api reloadxml" );
			return "ok";
		}
	}


	private	function normalizeSimpleXML($obj, &$result) {
		$data = $obj;
		if (is_object($data)) {
			$data = get_object_vars($data);
		}
		if (is_array($data)) {
			foreach ($data as $key => $value) {
				$res = null;
				$this->normalizeSimpleXML($value, $res);
				if (($key == '@attributes') && ($key)) {
					$result = $res;
				} else {
					$result[$key] = $res;
				}
			}
		} else {
			$result = $data;
		}
	}

	
	public function XML2JSON($file) {
		if (!file_exists($file)) {
			return false;
		}
		$xml = file_get_contents($file);
        
        $this->normalizeSimpleXML(simplexml_load_string($xml), $result);
        $json_ret = json_encode($result);
		return json_decode($json_ret,TRUE);
    }
	
	
    private function getJsonReponseClean( $response ){

        $pattern = '/(.*){(.*)}(.*)/m';
        
        $replacement = '{$2}';
        $response = preg_replace($pattern, $replacement, $response ); 

        try {
            $response = json_decode($response, true ) ;
        } catch (Exception $e) {
            return false ;
        }

        if( is_array( $response ) ){
            return $response ;
        }

        return false ;

    }
	
	public function is_number_isset($num){
		$users_path = config('vms.users_path');
		
		return file_exists($users_path."vmj_".$num.".xml");
	}
	
	public function checkWrtcMdpUidEnter($i){
		if( (empty($i["uid"])) || (empty($i["mdp"])) ){
			return false;
		}
		$user = DB::table('clients')->where('id', $i['uid'])->where('password', $i["mdp"])->get();
		$u = $user[0];
		
		$users_path = config('vms.users_path');
		
		if( !file_exists( $users_path ."vmj_".$u->number.".xml") ){
			return false;
		}
		

		\Session::forget('ulogin');
		\Session::forget('uname');
		\Session::forget('unumber');
		\Session::forget('upass');
		\Session::forget('utocall');
		
		\Session::set('ulogin',$u->login);
		\Session::set('uname',$u->name);
		\Session::set('unumber',$u->number);
		\Session::set('upass',$u->password);
		\Session::set('utocall',$u->room);
		
		return $u;
	}
	public function addLiveStreamWatcher($i){
		return DB::table('streamviewers')->insertGetId(
			[
				'datetime' => date("d.m.Y H:i:s"),
				'timestamp' => time(),
				'name' => $i["name"], 
				'login' => $i["login"],
				'ip' => $i["ip"],
				'brw' => $i["brw"],
				'desc' => $i["desc"]
			]
		);
	}
	
	public function checkWrtcPassAndEnter($i){
		
		if( empty($i["uid"]) ){
			return "No User ID";
		}
		
		if( (empty($i["password"])) && (empty($i["mdpassword"])) ){
			return "No Password";
		}
		/*if( (empty($i["uid"])) || (empty($i["password"]) && empty($i["mdpassword"])) ){
			return false;
		}*/
		$hPass = (!empty($i["mdpassword"])) ? $i["mdpassword"] : md5($i['password']);
		$user = DB::table('clients')->where('id', $i['uid'])->where('password', $hPass)->get();
		
		if( !empty($user[0]) ){
			return $this->enterToSystemIfGoodLogin($user[0]);
		} else {
			return "Bad Password (".$hPass .")";
		}
	}
	
	public function enterToSystemIfGoodLogin($u){
		if( $u->typeuser == "live" ){
			\Session::forget('ulogin');
			\Session::forget('uname');
			\Session::forget('unumber');
			\Session::forget('upass');
			\Session::forget('uroom');
			\Session::forget('utype');
			
			\Session::set('ulogin',$u->login);
			\Session::set('uname',$u->name);
			\Session::set('unumber',$u->number);
			\Session::set('upass',$u->password);
			\Session::set('uroom',$u->room);
			\Session::set('utype',$u->typeuser);
			
			return json_decode(json_encode($u),true);
		}
		$users_path = config('vms.users_path');
		
		if( !file_exists( $users_path ."vmj_".$u->number.".xml") ){
			return false;
		}
		
		if( !empty($u->sharenum) ){
			$s_sh = DB::table('clients')->where('login', $u->sharenum)->get();
			$s = $s_sh[0];
			\Session::forget('sharename');
			\Session::forget('sharenum');
			\Session::forget('shareroom');
			\Session::forget('sharepass');
			
			\Session::set('sharename',$s->name);
			\Session::set('sharenum',$s->number);
			\Session::set('sharepass',$s->password);
			\Session::set('shareroom',$s->room);
		
		}
	
		$arDbRooms = DB::table('rooms')->get();
		
		$uRooms = [];
		foreach($arDbRooms as $aRm ){
			if( !empty($aRm->users) ){
				$rUsrs = json_decode($aRm->users);
				if(in_array($u->number,$rUsrs)){
					$uRooms[] = $aRm->number;
				}
			}
		}
		
		\Session::forget('ulogin');
		\Session::forget('uname');
		\Session::forget('unumber');
		\Session::forget('upass');
		\Session::forget('utocall');
		\Session::forget('utype');
		
		\Session::set('ulogin',$u->login);
		\Session::set('uname',$u->name);
		\Session::set('unumber',$u->number);
		\Session::set('upass',$u->password);
		\Session::set('utocall',$u->room);
		\Session::set('utype',$u->typeuser);
		
		return json_decode(json_encode($u),true);
	}
	
	public function checkWrtcLogin($i){
		if( (empty($i["login"])) && (empty($i["number"])) ){
			return false;
		}
		$users_path = config('vms.users_path');
		
		if (is_numeric( $i["login"] ) ){
			$uid = DB::table('clients')->where('number', $i['number'])->where('typeuser', "webrtc")->value('id');
			if( !file_exists( $users_path ."vmj_".$i['number'].".xml") ){
				return false;
			}
			//$user = DB::select('select * from client where number = ?', [$input['number']]);
		} else {
			$uid = DB::table('clients')->where('login', $i['login'])->where('typeuser', "webrtc")->value('id');
			//$user = DB::select('select * from client where login = ?', [$input['login']]);
		}
		
		if( empty($uid) ){
			return false;
		} else {
			return $uid;
		}
	}
	/*EMILIO CHECK LOGIN DURING REGISTER*/
	public function checkLoginForRegister($i){
		if( empty($i["login"]) ){
			return false;
		}
		
		$uid = DB::table('clients')->where('login', $i['login'])->where('typeuser', "webinar")->value('id');

		if( empty($uid) ){
			return false;
		} else {
			return $uid;
		}
	}
	public function checkWebinarPassAndEnter($i){ 
		if( empty($i["uid"]) ){
			return "Login пустой";
		} 
		if ( empty($i["password"]) ){
			return "Password пустой";
		}

		$user = DB::table('clients')->where('id', $i['uid'])->where('password', md5($i['password']))->get();
		
		if ( empty($user) ){
			return "Пользователь не найден!";
		}
		
		$u = $user[0];

		//$arRooms = DB::table('webinars')->where('client', $i['uid'])->value("room");
/*
UPDATE        scores
SET           scores.name = p.name
FROM          scores s
INNER JOIN    people p
ON            s.personId = p.id
*/
		$updQuery = "UPDATE visits"
			." INNER JOIN webinars ON visits.room = webinars.room"
			." SET visits.active = 'N'"
			." WHERE webinars.client = ".$i['uid']."";
			
		$ansVsts = DB::update($updQuery);
		
		//var_dump($ansVsts);
		
		\Session::put('uid', $u->id);
		\Session::put('typeuser', $u->typeuser);
		\Session::put('name', $u->name);
		\Session::put('number', $u->number);
		\Session::put('password', $u->password);
		\Session::put('avatar', $u->avatar);
		
	
		return true;
	}
	
	public function checkLoginAndRegister($i){ 
		if( empty($i["login"]) ){
			return "Login пустой";
		} 
		if ( empty($i["password"]) ){
			return "Password пустой";
		}
		
		$uid = DB::table('clients')->where('login', $i['login'])->value('id');
		
		if ( !empty($uid) ){
			return "Логин занят";
		}
	
		$arfNums = $this->get_all_xml_users();
		$arWebinarNums = array_slice($arfNums,4100,4999);
		$maxNum = $this->array_key_last($arWebinarNums);
		
		$spr_number = (empty($maxNum)) ? 4100 : $maxNum+1;

		/*$data = array(
			$spr_number,
			$i["login"],
			md5($i["password"]),
			"Speaker_".$i["login"],
			"webinar"
		);*/
		
		$wid = DB::table('clients')->insertGetId(
			[
				'number' => $spr_number, 
				'login' => $i["login"],
				'password' => md5($i["password"]),
				'name' => "Speaker_".$i["login"],
				'typeuser' => "webinar"
			]
		);
		
		
		// = DB::insert('insert into clients (`number`, `login`, `password`, `name`, `typeuser`) values (?, ?, ?, ?, ?)',$data)
		if( $wid ){
			\Session::put('uid', $wid);
			\Session::put('usertype', "webinar");
			\Session::put('name', "Speaker_".$i["login"]);
			//\Auth::loginUsingId($wid, true);
			return $wid;
		} else {
			return "Error while saving user...";
		}

	}
	/*TODO END*/
	public function array_key_last($array) {
		if (!is_array($array) || empty($array)) {
			return NULL;
		}
		
		return array_keys($array)[count($array)-1];
	}

	private function get_all_xml_users(){
		$users_path = config('vms.users_path');
		$files = array_diff(scandir($users_path), array('.', '..'));
		if( empty($files) ) {return "";}
		$elems = array();
		foreach( $files as $xmlf ){
			$arUser = $this->XML2JSON( $users_path.$xmlf );
			if(empty($arUser)){ continue; }
			$elR = self::getUserDataFromXML($arUser);
			if( !empty($elR["number"]) ){
				$elems[$elR["number"]] = $elR;
			}
		}
		return $elems;

	}	
	
	public function get_one_layout($name){
		if( empty($name) ){ return "";}
		$lyt_path = config('vms.layouts_path');
		if( file_exists( $lyt_path ."vmj_".$name.".xml") ) {
			return $this->XML2JSON( $lyt_path ."vmj_".$name.".xml" );
		} else {
			return $lyt_path ."vmj_".$name.".xml"; //false;
		}
	}
	public function get_all_layouts(){
		$lyt_path = config('vms.layouts_path');
		$files = array_diff(scandir($lyt_path), array('.', '..'));
		if( empty($files) ) {return "Not files found";}
		$elems = array();
		foreach( $files as $xmlf ){
			//$arLayout = $this->XML2JSON( $lyt_path.$xmlf );
			if(empty($xmlf)){ continue; }
			//$elR = self::getUserDataFromXML($arUser);
			//$elems[$elR["number"]] = $elR;
			$elems[] = substr($xmlf,4,-4);
		}
		return $elems;
 
	}
	
	public function isset_layout($name){
		$layout_path = config('vms.layouts_path');
		return file_exists($layout_path."vmj_".$name.".xml");
	}
	private function save_layout_file($name, $data){
		$layout_path = config('vms.layouts_path');
		if( $myfile = fopen($layout_path."vmj_".$name.".xml", "w")) {
			fwrite($myfile, $data);
			fclose($myfile);
			return true;
		} else {
			return false;
		}
	}	
	
	private static function save_profile_file($name, $data){
		$prof_path = config('vms.profiles_path');
		if( $myfile = fopen($prof_path."vmj_".$name.".xml", "w")) {
			fwrite($myfile, $data);
			fclose($myfile);
			return true;
		} else {
			return false;
		}
	}	
	
	private static function save_user_file($name, $data){
		$users_path = config('vms.users_path');
		if( $myfile = fopen($users_path."vmj_".$name.".xml", "w")) {
			fwrite($myfile, $data);
			fclose($myfile);
			return true;
		} else {
			return false;
		}
	}
	
	
	public function conf_record_stop($i){
		if( empty($i["room"]) ){ return "No room";}
		if( empty($i["path"]) ){ return "No path";}
		$rec_line = 'conference '.$i["room"].' recording stop '.$i["path"];
		
		$response = $this->eRequest( "api ".$rec_line );
		
		return "ok";
	}
	
	public function conf_record_start($i){
		//conference 7777 recording start /recordings/777_19_nov_12_56_25.mp4
		if( empty($i["room"]) ){ return "No room";}
		
		$recs_path = $rPath = config('vms.records_path');
		
		$rec_line = 'conference '.$i["room"].' recording start '.$recs_path.''.$i["room"].'_'.date("d").'_'.date("M").'_'.date("H").'_'.date("i").'_'.date("s").'.mp4';
		
		$response = $this->eRequest( "api ".$rec_line );
		
		return "ok";

	}
		
	public function remove_room_file($name){
		$rooms_path = $rPath = config('vms.rooms_path');
		if( file_exists($rooms_path."vmj_".$name.".xml") ){
			unlink( $rooms_path."vmj_".$name.".xml" );
			$response = $this->eRequest( "api reloadxml" );
			return "ok";
		}
		return $name." - file is not found. (".$rooms_path."vmj_".$name.".xml)";
		
	}
	
	private function save_room_file($name, $data){
		$rooms_path = $rPath = config('vms.rooms_path');
		if( $myfile = fopen($rooms_path."vmj_".$name.".xml", "w")) {
			fwrite($myfile, $data);
			fclose($myfile);
			return true;
		} else {
			return false;
		}
	}

	
	//SYSTEM INFOS
	
	private function shapeSpace_system_load($interval = 1) {
		$coreCount = $this->shapeSpace_system_cores();
		$rs = sys_getloadavg();
		
		$interval = $interval >= 1 && 3 <= $interval ? $interval : 1;
		$load = $rs[$interval];
		return round(($load * 100) / $coreCount,2);
	}
	private function shapeSpace_system_cores() {
	
		$cmd = "uname";
		$OS = strtolower(trim(shell_exec($cmd)));
	 
		switch($OS) {
		   case('linux'):
			  $cmd = "cat /proc/cpuinfo | grep processor | wc -l";
			  break;
		   case('freebsd'):
			  $cmd = "sysctl -a | grep 'hw.ncpu' | cut -d ':' -f2";
			  break;
		   default:
			  unset($cmd);
		}
	 
		if ($cmd != '') {
		   $cpuCoreNo = intval(trim(shell_exec($cmd)));
		}
		
		return empty($cpuCoreNo) ? 1 : $cpuCoreNo;
		
	}
	private function shapeSpace_server_memory_usage() {
 
		$free = shell_exec('free');
		$free = (string)trim($free);
		$free_arr = explode("\n", $free);
		$mem = explode(" ", $free_arr[1]);
		$mem = array_filter($mem);
		$mem = array_merge($mem);
		$memory_usage = $mem[2] / $mem[1] * 100;
	 
		return $memory_usage;
		
	}
	function shapeSpace_disk_usage() {
	
		$disktotal = disk_total_space ('/');
		$diskfree  = disk_free_space  ('/');
		$diskuse   = round (100 - (($diskfree / $disktotal) * 100));
		
		return $diskuse;
		
	}

	public function is_port_open($host, $port){
		//$host = '193.33.186.70';
		//$port = 80;
		$waitTimeoutInSeconds = 1;
		if ($fp = fsockopen($host,$port,$errCode,$errStr,$waitTimeoutInSeconds)) {
		  $ret = true;
		} else {
		  $ret = false;
		}
		fclose($fp);
		
		return $ret;
	}
	
	public function apiCommand($cmd){
		$response = $this->eRequest( "api ".$cmd );
		return $response;
	}
	
	public function allCalls(){
		$response = $this->eRequest( "api show calls" );
		
		if( empty($response)) { return 0;}
		else {
			$arR = explode("\n",$response);
			
			
			$cls = array();
			$ch = array();
			$ch = array();
	
			
			foreach ( $arR as $a ){
				if( strlen($a) < 15 ){
					continue;
				}
				
				$arLine = explode(",",$a);

				if( $arLine[0] == "uuid" ){
					foreach( $arLine as $ah ){
						$ch[] = $ah;
					}
				} else {
					$onCall = array();
					foreach( $arLine as $ak=>$ah ){
						if(!empty($ch[$ak])){
							$onCall[$ch[$ak]] = $ah;
						}
						
					}
					$cls[] = $onCall;
				}
			}
			
			
			
			
		}
		//var_dump($cls);
		return count($cls);
	}
	
	public function sysFullInfo(){

		
		$cpu_stat = $this->shapeSpace_system_load(1);
		$memory_stat = $this->shapeSpace_server_memory_usage();
		$disk_stat = intval($this->shapeSpace_disk_usage());
		$all_calls = $this->allCalls(); //TODO: SOMEWHAT NOT WORKING...
		
		return array(
			"cpu"=>$cpu_stat,
			"memory"=>$memory_stat,
			"disk"=>$disk_stat,
			"calls"=>$all_calls
		);
		
		
	}
	
	
	
	/* WebINARS*/
	
	/* 	webinars
		поле	Тип	Комментарий
		id		int(30) Автоматическое приращение	
		client	int(20)	
		title	varchar(250)	
		desc	text	
		room	int(10) unsigned	
		params	text	
		files	text	
		created	tinytext	
		begin	tinytext
	
	*/
	// 
	public function exitFromWebinar($i){
		\Session::forget('webinar');
		return true;
	}
	public function enterToMyLastWebinar($i){
		/*$uid = \Session::get('uid');
		$arWbnrs = DB::table('webinars')->where('client', $uid)->get();
		$arWbnr = json_decode(json_encode($arWbnrs[0]),true);
		$arWbnr['params'] = json_decode($arWbnr['params'],true);
		\Session::set('webinar',$arWbnr);
		*/
		return true;
	}
	
	
	/*public function uploadFiles($data){
		
		$input = $_POST['files'];
		echo (json_encode($input));
	}*/
	
	public function enterToWebinarById($i){
		if( !empty($i["wid"]) ) {
			$arWebinars = DB::table('webinars')->where('id', $i["wid"])->get();
			/*$arWbnr = json_decode(json_encode($arWbnrs[0]),true);
			$arWbnr['params'] = json_decode($arWbnr['params']);
			\Session::set('webinar',$arWbnr);*/
			
			
			
			$webinar = json_decode(json_encode($arWebinars[0]),true);
			$webinar['params'] = json_decode($webinar['params'],true);
			\Session::put('webinar',$webinar);
					
					
			
			return true;
		}
		
	}
	public function removeMyWebinar($i){
		if( empty($i["wid"]) ){
			return "No Webinar ID";
		} else {
			$wroom = DB::table('webinars')->where('id', $i["wid"])->value('room');
			
			$remans = $this->remove_room_file($wroom);
			
			if( $remans == "ok" ){
				DB::table('webinars')->where('id',$i["wid"])->delete();
				return 0;
			}
		}
	}
	
	public function addNewWebinar($i){
		$uid = \Session::get('uid');

		if ( (!empty($i["begin_date"])) || (!empty($i["begin_time"])) ) {
			$d = explode("/",$i["begin_date"]);
			$t = explode(":",$i["begin_time"]);
			$bDateTime = mktime($d[0],$d[1],0, $d[0],$d[1],$d[2]) ;
		} else {
			$bDateTime = time();
		}
		//vmj_webinar_profile
		$cNums = config('vms.webinar_numbers'); 
		
		$newNum = $this->getNewRoomNumberByMinMax($cNums[0],$cNums[1]);

		$spr_number = (empty($newNum)) ? $cNums[0] : $newNum;
		
		$title = ( !empty($i["title"]) ) ? strip_tags($i["title"]) : "Вебинар_".date("YmdHis");
		$desc = ( !empty($i["descrition"]) ) ? strip_tags($i["descrition"]) : "_";
		
		$arParams = array(
			"resolution"=>( !empty($i["resolution"]) ) ? $i["resolution"] : "1920x1080",
			"files"=>true,
			"chat"=>true
		);
		
		$wCreate = time();
		$wLink = $this->generateRandomString();
		$wid = DB::table('webinars')->insertGetId(
			[
				'client' => (int)$uid, 
				'title' => $title,
				'desc' => $desc,
				'room' => (int)$spr_number,
				'params' => json_encode( $arParams ),
				'created' => $wCreate,
				'begin' => $bDateTime,
				'link' => $wLink
			]
		);
		
		if( is_numeric($wid) ){
			$sret = $this->saveRoom( array(
				"number"=> $spr_number,
				"name" => "vMajlis_Webinar_".$wid,
				// "member_flags" => '<action application="set" data="conference_member_flags=moderator"/>',
				"conference_controls" => '<action application="set" data="conference_controls=moderator"/>',
				"conf_profile" => 'vmj_webinar_profile'
				)
			);
			if( $sret == "ok"){
				return $wid;
			}else {
				DB::table('webinars')->where('id',$wid)->delete();
				return 'Can`t create webinar room!';
			}
		} else {
			return 'Can`t create webinar to Database';
		}
	}
	
	public function editMyWebinar($i){
		
		if( empty($i["wid"]) ){
			return "No Webinar ID";
		} else {
			$jParams = DB::table('webinars')->where('id', $i["wid"])->value('params');
		}
		$arParams = json_decode($jParams);
		
		$editData = array();
		
		if ( (!empty($i["begin_date"])) || (!empty($i["begin_time"])) ) {
			$d = explode("/",$i["begin_date"]);
			$t = explode(":",$i["begin_time"]);
			$editData['begin'] = mktime($d[0],$d[1],0, $d[0],$d[1],$d[2]) ;
		} 

		
		if ( !empty($i["title"]) ) { $editData['title'] = strip_tags($i["title"]); }
		if ( !empty($i["descrition"]) ) { $editData['descrition'] = strip_tags($i["descrition"]); }
		
		if( !empty($i["resolution"]) ){ $arParams["resolution"] = $i["resolution"]; }
		if( isset($i["files"]) ){ $arParams["files"] = $i["files"]; }
		if( isset($i["chat"]) ){ $arParams["chat"] = $i["chat"]; }
		
		$editData['params'] = json_encode( $arParams );
		
		DB::table('webinars')->where('id', $i["wid"])->update($editData);
		
		return $editData;
	}
	public function create_png_from_text($args){
		$font = "/usr/local/freeswitch/fonts/montserrat/Montserrat-Italic.otf";
		
		if( empty($args) ){ $args = "Default";}
		if( !is_array($args) ){
			$args = array( 'text' => $args );
		}
		
		$width = ( !empty($args["width"]) ) ? (int)$args["width"] : 1280; //640; //1920; //640;
		$height = ( !empty($args["height"]) ) ? (int)$args["height"] : 720; //480; //1080; //480;
		$text = $args["text"];
		
		if( strlen($text) > 150 ){
			$text = substr($text,0,150);
			$text = $text."...";
		}
		$file = ( !empty($args["file"]) ) ? $args["file"] : false;
		if( $width > 1000 ){
			$fontsize = 20;
		} else {
			$fontsize = 16;
		}
		
		$imgTxtBlock = imagecreate($width, 50);
		$imgTxtBack = imagecreate($width, 50);
		$img = imagecreate($width, $height);
		
		$bTxtBlocks = imagecolorallocate($imgTxtBlock, 0, 0, 0);
		imagecolorallocate($imgTxtBack, 255, 255, 255); //255, 255, 255
		$black = imagecolorallocate($img, 0,0,0); //3, 169, 244
		imagecolortransparent($img, $black); 

		//imagecolortransparent($imgTxtBlock, $bTxtBlocks); 
		
		$txtInTransparent = imagecolorallocate($imgTxtBlock, 255, 255, 255);
		
		
		//$txtInTransparent = imagecolorallocate($img, 255, 255, 255);
		
		$image_width = imagesx($img);
		$image_height = imagesy($img);
		
		$text_box = imagettfbbox($fontsize, 0, $font, $text);
		
		$text_width = $text_box[0] - $text_box[2];
		$text_height = $text_box[1] - $text_box[7];
		
		$x = 30; //$image_width - ($text_width / 2);
		$y = $image_height - ($text_height + 65);
	
		
		imagettftext($imgTxtBlock, $fontsize, 0, 20, 30, $txtInTransparent, $font, $text);

		imagecopymerge( $imgTxtBack, $imgTxtBlock,  0, 0, 0, 0, $image_width, 40, 60);
		
		imagecopymerge( $img, $imgTxtBack,  0, $y, 0, 0, $image_width, 40, 100);
		
		
		
		//imagettftext($img, $fontsize, 0, $x, $y, $txtInTransparent, $font, $text);
		//imagettftext($img, $fontsize, 0, $x, $y, $txtInTransparent, $font, $text.'-['.$image_height.']-['.$text_height.']-['.$y.']' ); //For tests
		
		if( !empty($file) ){
			imagepng($img, $file);
			imagedestroy($img);
			imagedestroy($imgTxtBlock);
			imagedestroy($imgTxtBack);
			return "ok";
		} else {
			header('Content-Type: image/png');
			imagepng($img);
			imagedestroy($img);
			imagedestroy($imgTxtBlock);
			imagedestroy($imgTxtBack);
		}
		
	}
	//getUserOS getUserIP getUserBrowser
	public static function getUserIP(){

		if (!empty($_SERVER['HTTP_X_FORWARD_FOR'])) {
			return $_SERVER['HTTP_X_FORWARD_FOR'];
		} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
			return $_SERVER['HTTP_X_FORWARDED_FOR'];
		} elseif (!empty($_SERVER['X-Real-IP'])) {
			return $_SERVER['X-Real-IP'];
		} elseif (!empty($_SERVER['HTTP_CLIENT_IP'])) {
			return $_SERVER['HTTP_CLIENT_IP'];
		} elseif(!empty($_SERVER['REMOTE_ADDR']))	{
			return $_SERVER['REMOTE_ADDR'];
		}
	}
	public static function getUserOS() { 

		$user_agent = $_SERVER['HTTP_USER_AGENT'];

		$os_platform  = "Unknown OS Platform";

		$os_array     = array(
							  '/windows nt 10/i'      =>  'Windows 10',
							  '/windows nt 6.3/i'     =>  'Windows 8.1',
							  '/windows nt 6.2/i'     =>  'Windows 8',
							  '/windows nt 6.1/i'     =>  'Windows 7',
							  '/windows nt 6.0/i'     =>  'Windows Vista',
							  '/windows nt 5.2/i'     =>  'Windows Server 2003/XP x64',
							  '/windows nt 5.1/i'     =>  'Windows XP',
							  '/windows xp/i'         =>  'Windows XP',
							  '/windows nt 5.0/i'     =>  'Windows 2000',
							  '/windows me/i'         =>  'Windows ME',
							  '/win98/i'              =>  'Windows 98',
							  '/win95/i'              =>  'Windows 95',
							  '/win16/i'              =>  'Windows 3.11',
							  '/macintosh|mac os x/i' =>  'Mac OS X',
							  '/mac_powerpc/i'        =>  'Mac OS 9',
							  '/linux/i'              =>  'Linux',
							  '/ubuntu/i'             =>  'Ubuntu',
							  '/iphone/i'             =>  'iPhone',
							  '/ipod/i'               =>  'iPod',
							  '/ipad/i'               =>  'iPad',
							  '/android/i'            =>  'Android',
							  '/blackberry/i'         =>  'BlackBerry',
							  '/webos/i'              =>  'Mobile'
						);

		foreach ($os_array as $regex => $value)
			if (preg_match($regex, $user_agent))
				$os_platform = $value;

		return $os_platform;
	}

	public static function getUserBrowser() {

		$user_agent = $_SERVER['HTTP_USER_AGENT'];

		$browser        = "Unknown Browser";

		$browser_array = array(
								'/msie/i'      => 'Internet Explorer',
								'/firefox/i'   => 'Firefox',
								'/safari/i'    => 'Safari',
								'/chrome/i'    => 'Chrome',
								'/edge/i'      => 'Edge',
								'/opera/i'     => 'Opera',
								'/netscape/i'  => 'Netscape',
								'/maxthon/i'   => 'Maxthon',
								'/konqueror/i' => 'Konqueror',
								'/mobile/i'    => 'Mobile Browser'
						 );

		foreach ($browser_array as $regex => $value)
			if (preg_match($regex, $user_agent))
				$browser = $value;

		return $browser;
	}
	public function create_png_from_text_ORIG($args){
		$font = "/usr/local/freeswitch/fonts/montserrat/Montserrat-Italic.otf";
		
		if( empty($args) ){ $args = "Default";}
		if( !is_array($args) ){
			$args = array( 'text' => $args );
		}
		
		$width = ( !empty($args["width"]) ) ? (int)$args["width"] : 1280; //640; //1920; //640;
		$height = ( !empty($args["height"]) ) ? (int)$args["height"] : 720; //480; //1080; //480;
		$text = $args["text"];
		
		if( strlen($text) > 150 ){
			$text = substr($text,0,150);
			$text = $text."...";
		}
		$file = ( !empty($args["file"]) ) ? $args["file"] : false;
		if( $width > 1000 ){
			$fontsize = 20;
		} else {
			$fontsize = 16;
		}
		
		$img = imagecreate($width, $height);
		
		$black = imagecolorallocate($img, 0, 0, 0);
		imagecolortransparent($img, $black);

		$txtInTransparent = imagecolorallocate($img, 255, 255, 255);
		
		$image_width = imagesx($img);
		$image_height = imagesy($img);
		
		$text_box = imagettfbbox($fontsize, 0, $font, $text);
		
		$text_width = $text_box[0] - $text_box[2];
		$text_height = $text_box[1] - $text_box[7];
		
		$x = 30; //$image_width - ($text_width / 2);
		$y = $image_height - ($text_height + 40);
	
		
		imagettftext($img, $fontsize, 0, $x, $y, $txtInTransparent, $font, $text);
		//imagettftext($img, $fontsize, 0, $x, $y, $txtInTransparent, $font, $text.'-['.$image_height.']-['.$text_height.']-['.$y.']' ); //For tests
		
		if( !empty($file) ){
			imagepng($img, $file);
			imagedestroy($img);
			return "ok";
		} else {
			header('Content-Type: image/png');
			imagepng($img);
			imagedestroy($img);
		}
		
	}
}