<?php namespace AloVoice; date_default_timezone_set('Asia/Tashkent');

class AloVoiceConnector
{
	const VERSION = '0.0.4';
	
    public $_client;
    public $_error;
    public $configs;
    public $settings;
    public $rootdir;
    public $alvhost;
    public $configFile;
    public $isAmi;
    public $appInstalled;
    public $isAdmin;
    public $alvagents;

    private $bxOutToken;
    private $TG;
    private $listenOn = false;

	public function __construct() {
		$this->configFile = __DIR__.'/config.json';
		$this->rootdir = dirname(dirname(dirname(__DIR__))).'/';
		$this->alvhost = (!empty($_SERVER["HTTP_HOST"])) ? 'https://'.$_SERVER["HTTP_HOST"].'/bx24/' : 'https://tug.alovoice.uz/bx24/';
		$this->settings = false; 
		$this->configs = $this->getConfigs();
		$this->isAmi=false;
		$this->appInstalled=false;
		$this->isAdmin=false;
		$this->alvagents=[];
	}
	
	public function isDevelopServer(){
		return ($_SERVER["HTTP_HOST"]=="tug.alovoice.uz");
	}
	
	public function isBillz(){
		return ($_SERVER["HTTP_HOST"]=="qamar.alovoice.uz");
	}
	
	public function consoleleads(){
		//consolerest.php
		$this->eLog($_SERVER['argv'],"------ AloVoiceConnector: Leads RUN ----------");

		return true;
	}
	
	public function inncheck($plc,$arPlcOpts){
		$entity = false;
		$tin = false;
		$confs = self::getCrmFiledsConfs();
		// if(!empty($_REQUEST["PLACEMENT"])){
			// $arPlc = explode("_",$_REQUEST["PLACEMENT"]);
			$arPlc = explode("_",$plc);
			// $arPlcOpts = json_decode($_REQUEST["PLACEMENT_OPTIONS"],true);
			if(!empty($arPlc[1]) && !empty($arPlcOpts["ID"])){
				$entity = [$arPlc[1]=>$arPlcOpts["ID"]];
				$entType = strtolower($arPlc[1]);
				$entTypeUP = strtoupper($arPlc[1]);
				$tinFieldsCode = $confs[$entType]['innfieldcode'];
				$resEntity = BxRest::call( 'crm.'.$entType.'.get', array("id"=>$arPlcOpts["ID"]) ); 
				self::eLog($resEntity,"------ Placements :: Entity (".$entType.") [".$tinFieldsCode."]GET Result: ----------");
				
				if(!empty($resEntity["result"]["ID"]) && !empty($resEntity["result"][$tinFieldsCode])){
					$tin = $resEntity["result"][$tinFieldsCode];
				}
			}
		// }
		// if(!empty($_REQUEST["lead"])){ $entity = ["LEAD"=>$_REQUEST["lead"]]; }
		// if(!empty($_REQUEST["deal"])){ $entity = ["DEAL"=>$_REQUEST["deal"]]; }
		// if(!empty($_REQUEST["company"])){ $entity = ["COMPANY"=>$_REQUEST["company"]]; }
		// if(!empty($_REQUEST["contact"])){ $entity = ["CONTACT"=>$_REQUEST["contact"]]; }
		
		if(!empty($entity) && !empty($tin)){
			echo $this->importByINN($tin,$entity);
		}
		else{
			echo 'Не найден ИНН: '.$tin;
		}
	}
	// public function innchecklead(){
		// $this->eLog($_REQUEST,"------ INN Check: REQUEST:");
		// //"inn":"307466926","leadid":"65592",
		// //{"inn":"307466926","document_id":["crm","CCrmDocumentLead","LEAD_65592"],"auth":{"domain":"4uz.bitrix24.ru","client_endpoint":"https:\/\/4uz.bitrix24.ru\/rest\/","server_endpoint":"https:\/\/oauth.bitrix.info\/rest\/","member_id":"cbb436f0f1d7471ce732a524cb8aeb17"}}
		// // $inn = $_REQUEST["inn"];
		// // $leadid = $_REQUEST["leadid"];
		// return $this->importByINN($_REQUEST["inn"],["LEAD"=>$_REQUEST["leadid"]]);
	// }
		
	public function alisa(){
		$this->eLog($_REQUEST,"------ Alisa: REQUEST:");
		$this->eLog($_SERVER,"------ Alisa: Server:");
		
		$inputs = file_get_contents('php://input');
		$irequest = json_decode($inputs, 1);
		$this->eLog($irequest,"------ Alisa: INPUT:");
		
		$arResponse = [ 
			"version" => "1.0",
			"response" => [
				"text" => "Приветствую! Я, АлоВойс.",
				"tts" => "Приветствую! Я Ало+Войс.",
				"buttons" => [
					[
						"title" => "Персональный кабинет",
						"payload" => ['func'=>'my'],
						"url" => "https://tug.alovoice.uz/",
						"hide" => true
					]
				],
				"end_session" => false
			]
		];
		
		if(
			!empty($irequest["request"]["nlu"]["tokens"]) 
			&& in_array("о",$irequest["request"]["nlu"]["tokens"]) 
			&& in_array("счётах",$irequest["request"]["nlu"]["tokens"])
		){
			$arResponse["response"]["text"] = "У вас на счету 5000 сум!";
			$arResponse["response"]["tts"] = "У ва+с на сче+ту 5000 су+м!";
			unset($arResponse["response"]["buttons"]);
		}
		
		elseif(
			!empty($irequest["request"]["nlu"]["tokens"]) 
			&& in_array("помощь",$irequest["request"]["nlu"]["tokens"])
		){
			$arResponse["response"]["text"] = "Я могу помочь Вам с информацией по Ало Войс.";
			$arResponse["response"]["tts"] = "Я могу помочь Вам с информацией по Ало Войс.";
			unset($arResponse["response"]["buttons"]);
		}
		
		elseif(
			!empty($irequest["request"]["nlu"]["tokens"]) 
			&& in_array("что",$irequest["request"]["nlu"]["tokens"])
			&& in_array("ты",$irequest["request"]["nlu"]["tokens"])
			&& in_array("умеешь",$irequest["request"]["nlu"]["tokens"])
		){
			$arResponse["response"]["text"] = "Я могу проинформировать Вас и состоянии и событиях в Ало Войс. Вы можете спросить у меня обо всем что касается Ало Войс.";
			$arResponse["response"]["tts"] = "Я могу проинформировать Вас и состоянии и событиях в Ало Войс. Вы можете спросить у меня обо всем что касается Ало Войс.";
			unset($arResponse["response"]["buttons"]);
		}
		
		elseif(
			!empty($irequest["request"]["nlu"]["tokens"]) 
			&& in_array("о",$irequest["request"]["nlu"]["tokens"]) 
			&& in_array("задачах",$irequest["request"]["nlu"]["tokens"])
		){
			$arResponse["response"]["text"] = "Вам сегодня надо встретится с Вашей командой!";
			$arResponse["response"]["tts"] = "Ва+м сего+дня на+до встре+титс+я с В+ашей ком+андой!";
			unset($arResponse["response"]["buttons"]);
		}
		
		elseif(!empty($irequest["request"]["payload"]["func"]) && $irequest["request"]["payload"]["func"]=="my"){
			$arResponse["response"]["text"] = "Добро пожаловать!";
			$arResponse["response"]["tts"] = "Добро пожаловать!";
			unset($arResponse["response"]["buttons"]);
		}
		else {
			$arResponse["response"]["text"] = "Извините, на этот вопрос пока не могу ответить, но мои разработчики работают над этим. Скоро отвечу. ";
			$arResponse["response"]["tts"] = "Извините, на этот вопрос пока не могу ответить, но мои разработчики работают над этим. Скоро отвечу. ";
			unset($arResponse["response"]["buttons"]);
		}
		
		// {
		  // "response": {
			// "text": "Здравствуйте! Это мы, хороводоведы.",
			// "tts": "Здравствуйте! Это мы, хоров+одо в+еды.",
			// "buttons": [
				// {
					// "title": "Надпись на кнопке",
					// "payload": {},
					// "url": "https://example.com/",
					// "hide": true
				// }
			// ],
			// "end_session": false
		  // },
		  // "analytics": {
				// "events": [
					// {
						// "name": "custom event"
					// },
					// {
						// "name": "another custom event",
						// "value": {
							// "field": "some value",
							// "second field": {
								// "third field": "custom value"
							// }
						// }
					// }
				// ]
			// },
		  // "version": "1.0"
		// }
		header('Content-Type: application/json');
		echo json_encode($arResponse);
		return true;
	}
	
	public function consolerest(){
		//consolerest.php
		$this->eLog($_SERVER['argv'],"------ AloVoiceConnector: RUN ARGV----------");
		$alvRest = new AloVoiceRest($this->configs);
		if($resRest = $alvRest->consoleMethod($_REQUEST)){
			$this->returnRes($resRest);
			echo "\n";
			return "\n";
		}
		return false;
	}
	
	public function run(){
		
		$this->eLog($_REQUEST,"------ AloVoiceConnector: RUN REQUEST----------");
		//$this->eLog($_FILES,"--== AloVoiceConnector FILES:");
		//$this->eLog($_SERVER,"------ AloVoiceConnector: RUN SERVER ----------");
		
		if(!empty($_REQUEST['afile'])){
			return $this->getWavAudio($_REQUEST['afile']);
		}

		if(!$this->isAuthorized()){
			return false;
		}
		
		$alvRest = new AloVoiceRest($this->configs);
		$resRest = $alvRest->doMethod($_REQUEST);
		// $this->eLog($resRest,"------ AloVoiceRest: RES:");
		if(!empty($resRest)){
			return $this->returnRes($resRest);
		}
		
		$alvActions = new AloVoiceActions($this->configs);
		$resAction = $alvActions->doAction();
		$this->eLog($resAction,"------ Action: RES:");
		if($resAction){
			return $this->returnRes($resAction);
		}

		$this->TG = new \TGA\ATelegram(); 
		$tgla = $this->TG->doTgMethod($_REQUEST);
		$this->eLog($tgla,"------ ATelegram: RES:");
		if(!empty($tgla)){
			if( !empty($tgla["action"]) ){
				$alvRest->doMethod($tgla["action"]);
			}
			return $this->returnRes($tgla);
			}
		
		$bxEvent = new BitrixEvents($this->configs);
		if(!empty($bxEventRes = $bxEvent->runEvents())){
			$this->eLog($bxEventRes["action"],"------ AloVoiceConnector: Action from Events ----------");
			if( !empty($bxEventRes["action"]) ){
				$alvRest->doMethod($bxEventRes["action"]);
			}
			return $this->returnRes($bxEventRes);
		}

		return $this->returnView();
		
		//$arRequires = $this->checkRequires();
		//echo '<PRE>'; var_dump($arRequires); echo '</PRE>';
	}


	public function install(){
		$this->eLog($_REQUEST,"------ AloVoiceConnector: INSTALL REQUEST----------");
		//$this->eLog($_SERVER,"------ AloVoiceConnector: INSTALL SERVER ----------");
		$resultInstall = BxRest::installApp();
		
		if(!empty($this->configs)){
			$alvAction = new AloVoiceActions($this->configs,true);
			$isAmi = $alvAction->checkAmi();
			$this->isAmi = (!empty($isAmi)) ? true : false;
		}
		$this->appInstalled = true;
		$this->goConfigurePage();
		return true;
	}
	
	public function isAuthorized(){
		if(
			(!empty($_REQUEST["save"])) && 
			($_REQUEST["save"]=="Y") && 
			(!empty($_REQUEST["access_token"])) &&
			(!empty($_REQUEST["application_token"])) &&
			(!empty($_REQUEST["refresh_token"])) &&
			(!empty($_REQUEST["expires_in"])) &&
			(!empty($_REQUEST["domain"])) &&
			(!empty($_REQUEST["member_id"])) &&
			(!empty($_REQUEST["ami_user"])) &&
			(!empty($_REQUEST["ami_pass"]))
		) {
			if(!$this->setConfigs()){
				$this->_error = "Указанными параметрами не удалось подключиться к Asterisk, пожалуйста перепроверьте!";
			} else {
				$this->isAmi = true;
				//$this->returnRes("Сохранилось...");
				//echo '<PRE>'; var_dump($this->configs); echo '</PRE>';
			}
			return $this->goConfigurePage();
		} 
		
		elseif( empty($this->configs) ){
			
			if( 
				(!empty($_REQUEST["AUTH_ID"]))  
				&& (!empty($_REQUEST["AUTH_EXPIRES"]))
				&& (!empty($_REQUEST["APP_SID"]))
				&& (!empty($_REQUEST["REFRESH_ID"]))
				&& (!empty($_REQUEST["member_id"]))
				//&& (!empty($_REQUEST["DOMAIN"]))
				//&& (!empty($_REQUEST["PLACEMENT"]))
			){
				$this->_error = "Параметры подключения к Asterisk не указаны!";
				return $this->goConfigurePage();
			} else {
				echo '<PRE>'; var_dump($_REQUEST); echo '</PRE>';
				$this->returnRes("У Вас нет допуска к этому странице! Закройте и больше сюда не лезьте!");
				return false;
			}
		}
		
		$this->settings = BxRest::getAppSettings();
		
		if(empty($this->settings)){
			$this->returnRes("У Вас нет допуска к этому странице!");
			return false;
		}
		
		$alvAction = new AloVoiceActions($this->configs);
		$checkAmi = $alvAction->checkAmi();
		$this->isAmi = (!empty($checkAmi)) ? true : false;
			
		if(!$this->isAmi){
			$this->_error = "Указанными параметрами не удалось подключиться к Asterisk, пожалуйста перепроверьте!";
			return $this->goConfigurePage();
		}
		
		return true;

	}
	
	public function saveBitrixSettings($s){
		if(empty($s)){
			$s = [
				'access_token' => htmlspecialchars($_REQUEST["access_token"]),
				'expires_in' => htmlspecialchars($_REQUEST['expires_in']),
				'application_token' => htmlspecialchars($_REQUEST['APP_SID']),
				'refresh_token' => htmlspecialchars($_REQUEST['refresh_token']),
				'domain' => htmlspecialchars($_REQUEST['DOMAIN']),
				'client_endpoint' => 'https://' . htmlspecialchars($_REQUEST['DOMAIN']) . '/rest/',
			];
		}
		return BxRest::saveAppSettings($s,true);
	}
	
	public function checkRequires(){
		$arResults = BxRest::call('batch',[
			'halt' => 0,
			'cmd' => [
				'app_info' => 'app.info',
				'bnd_events' => 'event.get',
				'sms_sender' => 'messageservice.sender.list',
			]
		]);
		
		return $arResults["result"]["result"];
	}
	
	public function registerRequires(){
		$regResults = BxRest::call('batch',[
			'halt' => 0,
			'cmd' => [
				'reg_sms_sender' => 'messageservice.sender.add?'.http_build_query(
					array(
						'CODE' => 'alosms',
						'TYPE' => 'SMS',
						'HANDLER' => $this->alvhost,
						'NAME' => 'AloSms',
						'DESCRIPTION' => 'Sms provider for sending sms by AloVoice'
					)
				),
				'bnd_externalcall' => 'event.bind?'.http_build_query(
					array(
						'event' => 'ONEXTERNALCALLSTART',
						'handler' => $this->alvhost,
					)
				),
				'bnd_extcallback' => 'event.bind?'.http_build_query(
					array(
						'event' => 'ONEXTERNALCALLBACKSTART',
						'handler' => $this->alvhost,
					)
				),
			]
		]);
		
		//echo '<PRE>'; var_dump($regResults["result"]["result"]); echo '</PRE>';
		return $regResults["result"]["result"];
	}

	public function unregisterRequires(){
		$delResults = BxRest::call('batch',[
			'halt' => 0,
			'cmd' => [
				'reg_sms_sender' => 'messageservice.sender.delete?'.http_build_query(array(
						'CODE' => 'alosms',
					)
				),
				'unbnd_externalcall' => 'event.unbind?'.http_build_query(
					array(
						'event' => 'ONEXTERNALCALLSTART',
						'handler' => $this->alvhost,
					)
				),
				'unbnd_extcallback' => 'event.unbind?'.http_build_query(
					array(
						'event' => 'ONEXTERNALCALLBACKSTART',
						'handler' => $this->alvhost,
					)
				),
				
			]
		]);
	}
	
	public function setConfigs(){
		if(empty( $_REQUEST["ami_user"] ) || empty($_REQUEST["ami_pass"]) ){ return false; }
		$cnf = array(
			'bitrix_domain' => htmlspecialchars($_REQUEST['domain']),
			'alovoice_host' => $this->alvhost, //$_SERVER["SCRIPT_URI"],
			'files_folder' => "files/",
			'sounds_folder' => "files/sounds/",
			'asterisk_host' => (!empty($_REQUEST["ami_host"])) ? $_REQUEST["ami_host"] : '127.0.0.1',
			'asterisk_scheme' => "tcp://",
			'asterisk_port' => (!empty($_REQUEST["ami_port"])) ? $_REQUEST["ami_port"] : '5038',
			'asterisk_username' => $_REQUEST["ami_user"],
			'asterisk_secret' => $_REQUEST["ami_pass"],
			'connect_timeout' => (!empty($_REQUEST["connect_timeout"])) ? $_REQUEST["connect_timeout"] : 100,
			'read_timeout' => (!empty($_REQUEST["read_timeout"])) ? $_REQUEST["read_timeout"] : 1000,
		);

		
		$oldConfs = self::getConfigs();
		$arNewConf = [];
		if(!empty($oldConfs)){
			$arNewConf = $oldConfs;
		}
		
		if(!empty($cnf['bitrix_domain'])){ $arNewConf['bitrix_domain'] = $cnf['bitrix_domain'];  }
		if(!empty($cnf['alovoice_host'])){ $arNewConf['alovoice_host'] = $cnf['alovoice_host'];  }
		if(!empty($cnf['files_folder'])){ $arNewConf['files_folder'] = $cnf['files_folder'];  }
		if(!empty($cnf['asterisk_host'])){ $arNewConf['asterisk_host'] = $cnf['asterisk_host'];  }
		if(!empty($cnf['asterisk_scheme'])){ $arNewConf['asterisk_scheme'] = $cnf['asterisk_scheme'];  }
		if(!empty($cnf['asterisk_port'])){ $arNewConf['asterisk_port'] = $cnf['asterisk_port'];  }
		if(!empty($cnf['asterisk_username'])){ $arNewConf['asterisk_username'] = $cnf['asterisk_username'];  }
		if(!empty($cnf['asterisk_secret'])){ $arNewConf['asterisk_secret'] = $cnf['asterisk_secret'];  }
		if(!empty($cnf['connect_timeout'])){ $arNewConf['connect_timeout'] = $cnf['connect_timeout'];  }
		if(!empty($cnf['read_timeout'])){ $arNewConf['read_timeout'] = $cnf['read_timeout'];  }
		
		$alvAction = new AloVoiceActions($arNewConf);
		$isAmi = $alvAction->checkAmi();

		if($isAmi == "Success"){
			$jsonConfigs = json_encode($arNewConf);
			if( file_put_contents($this->configFile, $jsonConfigs) ){
				$this->configs = $arNewConf;
				
				$arBxSettings = array(
					'access_token' => htmlspecialchars($_REQUEST["access_token"]),
					'expires_in' => htmlspecialchars($_REQUEST['expires_in']),
					'application_token' => htmlspecialchars($_REQUEST['application_token']),
					'refresh_token' => htmlspecialchars($_REQUEST['refresh_token']),
					'domain' => htmlspecialchars($_REQUEST['domain']),
					'client_endpoint' => 'https://' . htmlspecialchars($_REQUEST['domain']) . '/rest/',	
				);
			
				if($this->saveBitrixSettings($arBxSettings)){
					//$appInfoRes = BxRest::call("app.info");
					//$this->returnRes($appInfoRes);
					return $this->configs;
				} 
				
				if(file_exists($this->configFile)){
					unlink($this->configFile);
				}
			} 
		}
		return false;
	}
	
	public function setConfigValues($settings){
		$conf_file = __DIR__.'/config.json';
		
		if(!empty($settings)){
			$jsSet = json_encode($settings);
			if(file_put_contents($conf_file,$jsSet)){
				return $settings;
			}
		}
		
		return false;
	}
	
	public function getConfigs(){
		$conf_file = __DIR__.'/config.json';
		
		$return = array();
		
		if(file_exists($conf_file)){
			$return = json_decode(file_get_contents($conf_file), true);
		} 
		
		if(!empty($return)){
			$return['basedir'] = dirname(dirname(dirname(__DIR__)));
			
			if(empty($return['sounds_folder'])){
				$return['sounds_folder'] = "files/sounds/";
			}
			
			return $return;
		} else {
			return false;
		}
	}
	
	public function getCrmFiledsConfs(){
		$cffile = __DIR__.'/crmfields.json';
		$ret = false;
		if(file_exists($cffile)){
			$ret = json_decode(file_get_contents($cffile), true);
		}
		
		return $ret;
	}
	
	public function getCrmFileds(){
		$arFiledsResults = BxRest::call('batch',[
			'halt' => 0,
			'cmd' => [
				'lead_fields' => 'crm.lead.fields',
				'deal_fields' => 'crm.deal.fields',
				'company_fields' => 'crm.company.fields',
				'contact_fields' => 'crm.contact.fields',
				'requisite_fields' => 'crm.requisite.fields',
				'requisite_temps' => 'crm.requisite.preset.list?'.http_build_query( array("order"=>array("ID"=>"ASC"),"filter:"=>array("COUNTRY_ID"=>"1"),"select"=>array("ID","NAME")) )
			]
		]);
		
		if(!empty($arFiledsResults["result"])){
			$allFields = $arFiledsResults["result"]["result"];
		}
		else {
			$allFields = [];
		}
		
		$confs = self::getCrmFiledsConfs();
		if(!empty($confs)){
			$allFields["conf"] = $confs;
		} 
		else{
			$allFields["conf"] = array(
				"requisite" => array(),
				"fizrequisite" => array()
			);
		}

		return $allFields;
	}
	
	public function getCrmRequisiteTemplates(){
		$resReqFields = BxRest::call("crm.requisite.fields");
		$allFields["requisite_fields"] = $resReqFields["result"] ;
		return $allFields;
	}
	
	public function saveCrmFileds($data){
		$cffile = __DIR__.'/crmfields.json';
		
		if(!empty($data)){
			$jsSet = json_encode($data);
			if(file_put_contents($cffile,$jsSet)){
				return $data;
			}
		}
		
		return false;
	}
	
	
	public function makeContactsByInn($p,$ent=[]){
		$innCeoContacts = [];

		if(!empty($p["gdTelWork"])){
			$innCeoContacts[] = array("VALUE" => $p["gdTelWork"], "VALUE_TYPE" => "WORK");
		}
		if(!empty($p["gdTelHome"])){
			$innCeoContacts[] = array("VALUE" => $p["gdTelHome"], "VALUE_TYPE" => "HOME");
		}
		
		// $etnFldIdName = key($ent)."_ID";
		
		$addContactFields = [
			"NAME" => $p["gdFullName"],
			"OPENED" => "Y",
			"ASSIGNED_BY_ID" => 1,
			"TYPE_ID" => "CLIENT",
			"SOURCE_ID" => "SELF",
			"POST" => "Руководитель",
			// $etnFldIdName => current($ent),
			"PHONE" => $innCeoContacts,
			"UTM_CONTENT" => $p["gdTin"],
		];
			
		self::eLog($addContactFields,"------ ALVC :: ADD DIR CONTACT Params...:");

		$resContactAdd = BxRest::call( 'crm.contact.add', array(
			"fields" => $addContactFields
		));
		
		if(!empty($p["gbTelWork"])){
			$innBuxContacts[] = array("VALUE" => $p["gbTelWork"], "VALUE_TYPE" => "WORK");
		}
		if(!empty($p["gbTelHome"])){
			$innBuxContacts[] = array("VALUE" => $p["gbTelHome"], "VALUE_TYPE" => "HOME");
		}
		
		
		$addContactFields["NAME"] = $p["gbFullName"];
		$addContactFields["POST"] = "Бухгалтер";
		$addContactFields["PHONE"] = $innBuxContacts;
		$addContactFields["UTM_CONTENT"] = $p["gbTin"];

		self::eLog($addContactFields,"------ ALVC :: ADD BUX CONTACT Params...:");

		$resContactAdd = BxRest::call( 'crm.contact.add', array(
			"fields" => $addContactFields
		));
		
		return (!empty($resContactAdd["result"])) ? $resContactAdd["result"] : false;
		
	}
	
	public function checkTgContact($ent){
		return true;
		if(preg_match("/imol\|alotg/",json_encode($ent))){
			return true;
		}
		$arCheckNumbers = []; 
		//{"result":{"ID":"65444","TITLE":"\u0417\u0430\u0434\u0430\u0447\u0438+ \u0434\u043b\u044f \"INTERHOTEL\"","HONORIFIC":"","NAME":"FARRUX","SECOND_NAME":"MANSUROVICH","LAST_NAME":"SHAKIROV","COMPANY_TITLE":"\u041e\u0411\u0429\u0415\u0421\u0422\u0412\u041e \u0421 \u041e\u0413\u0420\u0410\u041d\u0418\u0427\u0415\u041d\u041d\u041e\u0419 \u041e\u0422\u0412\u0415\u0422\u0421\u0422\u0412\u0415\u041d\u041d\u041e\u0421\u0422\u042c\u042e \"INTERHOTEL\"","COMPANY_ID":"","CONTACT_ID":"","IS_RETURN_CUSTOMER":"N","BIRTHDATE":"","SOURCE_ID":"CALL","SOURCE_DESCRIPTION":"\u0417\u0432\u043e\u043d\u043e\u043a \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u043b \u043d\u0430 \u043d\u043e\u043c\u0435\u0440: +998712037006.","STATUS_ID":"6","STATUS_DESCRIPTION":"","POST":"\u0413\u0435\u043d\u0435\u0440\u0430\u043b\u044c\u043d\u044b\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440","COMMENTS":"Farrukh Mansurovich","CURRENCY_ID":"UZS","OPPORTUNITY":"0.00","IS_MANUAL_OPPORTUNITY":"N","HAS_PHONE":"Y","HAS_EMAIL":"N","HAS_IMOL":"Y","ASSIGNED_BY_ID":"8","CREATED_BY_ID":"8","MODIFY_BY_ID":"6","DATE_CREATE":"2021-06-21T09:38:23+03:00","DATE_MODIFY":"2021-06-22T17:27:18+03:00","DATE_CLOSED":"","STATUS_SEMANTIC_ID":"P","OPENED":"Y","ORIGINATOR_ID":"","ORIGIN_ID":"","ADDRESS":"AMIR TEMUR SHOX KO`CHASI 107 A-UY","ADDRESS_2":"","ADDRESS_CITY":"","ADDRESS_POSTAL_CODE":"","ADDRESS_REGION":"\u042e\u043d\u0443\u0441\u0430\u0431\u0430\u0434\u0441\u043a\u0438\u0439 \u0440\u0430\u0439\u043e\u043d","ADDRESS_PROVINCE":"\u0433\u043e\u0440\u043e\u0434 \u0422\u0430\u0448\u043a\u0435\u043d\u0442","ADDRESS_COUNTRY":"","ADDRESS_COUNTRY_CODE":"","ADDRESS_LOC_ADDR_ID":"106750","UTM_SOURCE":"","UTM_MEDIUM":"","UTM_CAMPAIGN":"","UTM_CONTENT":"306533130","UTM_TERM":"","UF_CRM_60B10F9B41134":"","UF_CRM_1623010700071":"0","UF_CRM_1623313128984":"","UF_CRM_1623313151583":"","UF_CRM_1623313168504":"","UF_CRM_1623423829192":"","UF_CRM_1619575012878":"","UF_CRM_5E1651086524E":"","UF_CRM_5DDD0FA90F0C8":"@farfom","UF_CRM_5D9779809395B":"","UF_CRM_1622711899478":"","UF_CRM_1622973128":"\u041e\u0431\u0449\u0435\u0441\u0442\u0432\u043e \u0441 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u043e\u0439 \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u044c\u044e","UF_CRM_1622711887190":"\u0413\u043e\u0441\u0442\u0438\u043d\u0438\u0446\u044b \u0438 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0435 \u043c\u0435\u0441\u0442\u0430 \u043f\u0440\u043e\u0436\u0438\u0432\u0430\u043d\u0438\u044f","UF_CRM_1622711873311":"1","UF_CRM_1622711930269":"","UF_CRM_1622117814212":"306533130","UF_CRM_1622711954430":"25.06.2019","UF_CRM_1622711963973":"737415","UF_CRM_1622711940630":"","UF_CRM_1622711973694":"\u0414\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0438 \u0438\u043c\u0435\u044e\u0449\u0438\u0435 \u043d\u0430\u043b\u043e\u0433\u043e\u0432\u044b\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u0430","UF_CRM_1622715062745":"20208000105097079001","UF_CRM_1622738392572":"546559301","UF_CRM_1622738308815":"\u0425\u0410\u0428\u0418\u041c\u041e\u0412 \u0410\u0411\u0417\u0410\u041b\u0425\u041e\u041d \u041c\u0423\u0420\u0410\u0422\u0425\u041e\u0414\u0416\u0410\u0415\u0412\u0418\u0427","UF_CRM_1622738365245":"452137075","UF_CRM_1622711917462":"","UF_CRM_1582891916":"","UF_CRM_1582892424":"","UF_CRM_60B10F9B25AB0":"","UF_CRM_60B10F9B36EDA":"","UF_CRM_5E14B03756729":"","UF_CRM_1582892605":"","UF_CRM_1619574660912":"","UF_CRM_1619575156462":"","UF_CRM_1619602082396":"","UF_CRM_1619574711758":"","UF_CRM_1619574786669":"","UF_CRM_1619574814622":"","UF_CRM_1619574852198":"","UF_CRM_1619574952758":"","UF_CRM_1619575186221":"","UF_CRM_1619575050158":"","UF_CRM_1619575115710":"","UF_CRM_1619575222798":[],"UF_CRM_1619575346238":"","UF_CRM_1619575270814":"","UF_CRM_1619577003819":"","UF_CRM_1619575798500":"","UF_CRM_1621778882":"","UF_CRM_SECRET":"","UF_CRM_5E165108724DD":"","UF_CRM_5E165EACCD3EB":"","UF_CRM_1615818076388":"","UF_CRM_5E1651088363E":"","UF_CRM_5E165EACDFB12":"","UF_CRM_5E165EACEB2B6":"","UF_CRM_1622516555":[],"PHONE":[{"ID":"222744","VALUE_TYPE":"OTHER","VALUE":"+998909690951","TYPE_ID":"PHONE"},{"ID":"222756","VALUE_TYPE":"WORK","VALUE":"+998781403950","TYPE_ID":"PHONE"},{"ID":"222758","VALUE_TYPE":"OTHER","VALUE":"+998901759252","TYPE_ID":"PHONE"},{"ID":"222856","VALUE_TYPE":"WORK","VALUE":"998901759252","TYPE_ID":"PHONE"}],"IM":[{"ID":"222854","VALUE_TYPE":"IMOL","VALUE":"imol|alotg|2|$01000000047a4a0c71540682777298e0|600","TYPE_ID":"IM"}]},"time":{"start":"1624372039.4008","finish":"1624372039.5341","duration":"0.13333511352539","processing":"0.016435861587524","date_start":"2021-06-22T17:27:19+03:00","date_finish":"2021-06-22T17:27:19+03:00"}}
		
		if(!empty($ent["UTM_CONTENT"]) && $ent["UTM_CONTENT"]=="DONE"){
			return true;
		}
		
		self::eLog($ent["PHONE"],"\n\n------========= ALVC :: TG Phone Contact Validating....");
		
		if(!empty($ent["PHONE"])){
			foreach($ent["PHONE"] as $ph){
				$phone = self::nn($ph["VALUE"],true); //preg_replace("/[^0-9]/", '', $ph["VALUE"]);
				
				if(!empty($phone) && strlen($phone)>8 && !in_array($phone,$arCheckNumbers)){
					
					self::eLog($ph["VALUE"],"------ ALVC :: BX Phone for VALIDATED in Loop [".$phone."]:");
					
					$arCheckNumbers[] = $phone;
					$phCode = substr($phone,-9,2);
					if(in_array($phCode,["33","88","90","91","93","94","95","97","98","99"])){
						$tgPhone = "998".substr($phone,-9);
						$TG = new \TGA\ATelegram(); 
						$tgRes = $TG->add_tgimol($tgPhone);
						self::eLog($tgRes,"------========= ALVC :: TG Phone Contact Validate:");
						
						if(!empty($tgRes["action"])){
							$alvRest = new AloVoiceRest($this->configs);
							$resRest = $alvRest->doMethod($tgRes["action"]);
							
							self::eLog($resRest,"------========= ALVC :: After TG Action RES:");
						}
						//{"id":"$01000000b21f0d369cd41d5a4713a15d","peer_type":"user","peer_id":906829746,"print_name":"\u041a\u0430\u043c\u043e\u043b\u0430_\u0413\u043e\u0444\u0443\u0440\u043e\u0432\u0430","flags":65537,"first_name":"\u041a\u0430\u043c\u043e\u043b\u0430","last_name":"\u0413\u043e\u0444\u0443\u0440\u043e\u0432\u0430","phone":"998994436349","username":"Kamaolala"}
					}
				}
			}
		}
	}
	
	public function crm_entite_codes($code=false) {
		$entTypes = array(
			"LEAD" => 1,
			"DEAL" => 2,
			"CONTACT" => 3,
			"COMPANY" => 4,
			"INVOICE" => 5,
			"Quote" => 7,
			"Requisites" => 8
		);
		$code = strtoupper($code);
		return (!empty($code) && !empty($entTypes[$code])) ? $entTypes[$code] : $entTypes;
	}
	
	public function crm_entites() {
		return [
			'lead'=>"Лид",
			'deal'=>"Сделка",
			'company'=>"Компания", 
			'contact'=>"Контакт", 
			'requisite'=>"Реквизит", 
		];
	}
	
	//{"result":{"ID":"65380","TITLE":"994436349 - \u0412\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0437\u0432\u043e\u043d\u043e\u043a","HONORIFIC":"","NAME":"","SECOND_NAME":"","LAST_NAME":"","COMPANY_TITLE":"","COMPANY_ID":"","CONTACT_ID":"","IS_RETURN_CUSTOMER":"N","BIRTHDATE":"","SOURCE_ID":"CALL","SOURCE_DESCRIPTION":"\u0417\u0432\u043e\u043d\u043e\u043a \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u043b \u043d\u0430 \u043d\u043e\u043c\u0435\u0440: +998994008840.","STATUS_ID":"NEW","STATUS_DESCRIPTION":"","POST":"","COMMENTS":"","CURRENCY_ID":"UZS","OPPORTUNITY":"0.00","IS_MANUAL_OPPORTUNITY":"N","HAS_PHONE":"Y","HAS_EMAIL":"N","HAS_IMOL":"N","ASSIGNED_BY_ID":"1","CREATED_BY_ID":"8","MODIFY_BY_ID":"6","DATE_CREATE":"2021-06-14T11:19:34+03:00","DATE_MODIFY":"2021-06-22T16:57:04+03:00","DATE_CLOSED":"","STATUS_SEMANTIC_ID":"P","OPENED":"Y","ORIGINATOR_ID":"","ORIGIN_ID":"","ADDRESS":"","ADDRESS_2":"","ADDRESS_CITY":"","ADDRESS_POSTAL_CODE":"","ADDRESS_REGION":"","ADDRESS_PROVINCE":"","ADDRESS_COUNTRY":"","ADDRESS_COUNTRY_CODE":"","ADDRESS_LOC_ADDR_ID":"","UTM_SOURCE":"","UTM_MEDIUM":"","UTM_CAMPAIGN":"","UTM_CONTENT":"","UTM_TERM":"","UF_CRM_60B10F9B41134":"","UF_CRM_1623010700071":"0","UF_CRM_1623313128984":"","UF_CRM_1623313151583":"","UF_CRM_1623313168504":"","UF_CRM_1623423829192":"","UF_CRM_1619575012878":"","UF_CRM_5E1651086524E":"","UF_CRM_5DDD0FA90F0C8":"","UF_CRM_5D9779809395B":"","UF_CRM_1622711899478":"","UF_CRM_1622973128":"","UF_CRM_1622711887190":"","UF_CRM_1622711873311":"1","UF_CRM_1622711930269":"","UF_CRM_1622117814212":"","UF_CRM_1622711954430":"","UF_CRM_1622711963973":"","UF_CRM_1622711940630":"","UF_CRM_1622711973694":"","UF_CRM_1622715062745":"","UF_CRM_1622738392572":"","UF_CRM_1622738308815":"","UF_CRM_1622738365245":"","UF_CRM_1622711917462":"","UF_CRM_1582891916":"","UF_CRM_1582892424":"","UF_CRM_60B10F9B25AB0":"","UF_CRM_60B10F9B36EDA":"","UF_CRM_5E14B03756729":"","UF_CRM_1582892605":"","UF_CRM_1619574660912":"","UF_CRM_1619575156462":"","UF_CRM_1619602082396":"","UF_CRM_1619574711758":"","UF_CRM_1619574786669":"","UF_CRM_1619574814622":"","UF_CRM_1619574852198":"","UF_CRM_1619574952758":"","UF_CRM_1619575186221":"","UF_CRM_1619575050158":"","UF_CRM_1619575115710":"","UF_CRM_1619575222798":[],"UF_CRM_1619575346238":"","UF_CRM_1619575270814":"","UF_CRM_1619577003819":"","UF_CRM_1619575798500":"","UF_CRM_1621778882":"","UF_CRM_SECRET":"","UF_CRM_5E165108724DD":"","UF_CRM_5E165EACCD3EB":"","UF_CRM_1615818076388":"","UF_CRM_5E1651088363E":"","UF_CRM_5E165EACDFB12":"","UF_CRM_5E165EACEB2B6":"","UF_CRM_1622516555":[],"PHONE":[{"ID":"222324","VALUE_TYPE":"WORK","VALUE":"994436349","TYPE_ID":"PHONE"}]},"time":{"start":"1624370226.3558","finish":"1624370226.5127","duration":"0.15696096420288","processing":"0.020624876022339","date_start":"2021-06-22T16:57:06+03:00","date_finish":"2021-06-22T16:57:06+03:00"}}
	public function importByINN($tin,$p=false,$isUpd=false){
		$arCrmConfs = self::getCrmFiledsConfs();
		$isProcess = false;
		$actEntType = 'lead';
		$actEntId = false;
		$innPersonContacts = [];
		$entTypes = array(
			"LEAD" => 1,
			"DEAL" => 2,
			"CONTACT" => 3,
			"COMPANY" => 4,
			"INVOICE" => 5,
			"Quote" => 7,
			"Requisites" => 8
		);
		
		if(!empty($p)){
			$actEntType =  key($p);
			$actEntTypeId = $entTypes[$actEntType];
			$actEntId = current($p);
		}
		
		self::eLog($arCrmConfs,"------ importByINN :: CONFS:");
		
		$actEntTypeLwr =  strtolower($actEntType);
		$actEntTypeUp =  strtoupper($actEntType);
		
		if(empty($arCrmConfs[$actEntTypeLwr])){
			self::eLog($arCrmConfs,"------ CRm Fields ei EMPTY for TIN:".$tin);
			return false;
		}
		

		$resTaxINN = self::requesTaxInn($tin);
		self::eLog($resTaxINN,"------ Connector :: LEAD Tax INFOs (".$tin."):");
		
		if(empty($resTaxINN)){
			if(!empty($actEntId)){
				$resLeadInfLst = BxRest::call( 'crm.timeline.comment.add', array(
					"fields"=>array( 
						"ENTITY_TYPE"=> $actEntTypeLwr,
						"ENTITY_ID"=> $actEntId,
						"COMMENT"=> "Не найдено информация по ИНН: [B]".$tin."[/B]"
					)
				));
			}
		}
		
		$taxFieldsCodes = self::innTaxFields();
		self::eLog($taxFieldsCodes,"------ Connector :: LEAD taxFieldsCodes :");
		
		$infoHTML = "[COLOR=#00aeef][SIZE=12pt][B]Информация по ИНН[/B][/SIZE][/COLOR] \n";
		foreach($taxFieldsCodes as $tcode=>$tval){
			$tcode = substr($tcode,4);
			$infoHTML .= $tval.': [B]'.$resTaxINN[$tcode]."[/B] \n";
		}

		$resLeadInfLst = BxRest::call( 'crm.timeline.comment.add', array(
			"fields"=>array( 
				"ENTITY_TYPE"=> ($actEntType) ? $actEntType : 'company',
				"ENTITY_ID"=> $actEntId,
				"COMMENT"=> $infoHTML //json_encode($resTaxINN,JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE)
			)
		));
		 
	  
	  
		$innAllContacts = [];

		if(!empty($resTaxINN["gdTelWork"])){
			$innAllContacts[] = array("VALUE" => $resTaxINN["gdTelWork"], "VALUE_TYPE" => "WORK");
		}
		if(!empty($resTaxINN["gdTelHome"])){
			$innAllContacts[] = array("VALUE" => $resTaxINN["gdTelHome"], "VALUE_TYPE" => "HOME");
		}
		if(!empty($resTaxINN["gbTelWork"])){
			$innAllContacts[] = array("VALUE" => $resTaxINN["gbTelWork"], "VALUE_TYPE" => "WORK");
		}
		if(!empty($resTaxINN["gbTelHome"])){
			$innAllContacts[] = array("VALUE" => $resTaxINN["gbTelHome"], "VALUE_TYPE" => "HOME");
		}
			

		$entTypeLwr = (!empty($actEntType)) ? strtolower($actEntType) : 'lead';
		$arEntMtdFields = $arCrmConfs[$entTypeLwr];

		if(!empty($arEntMtdFields)){
			$arEntityNewParams = [ "UTM_CONTENT" => $tin ];
			
			foreach($arEntMtdFields as $entFld=>$innFld){
				$tFieldsName = (substr($innFld,0,4)=="tax_") ? substr($innFld,4) : $innFld;
				$arEntityNewParams[$entFld] =  (!empty($resTaxINN[$tFieldsName])) ? $resTaxINN[$tFieldsName] : "";
				
				if($entFld == "TITLE") { $arEntityNewParams[$entFld] = $arEntityNewParams[$entFld]." (".$tin.")"; }
			}

			if(!empty($innAllContacts)){
				$arEntityNewParams["PHONE"] = $innAllContacts;
			}

			self::eLog($arEntityNewParams,"------ Connector :: [".$entTypeLwr."] Add/Update Params(".$tin."):");

			if(!empty($actEntId)){ 
				
				$resNewEntityUpdated = BxRest::call( 'crm.'.$entTypeLwr.'.update', array(
					"id" => $actEntId,
					"fields" => $arEntityNewParams
				));
			}
			else {
				$resNewEntityAdded = BxRest::call( 'crm.'.$entTypeLwr.'.add', array(
					"fields" => $arEntityNewParams
				));
				if(!empty($resNewEntityAdded["result"])){
					$actEntId = $resNewEntityAdded["result"];
				}
			}
			$preset_id = 6;
			$entTypeUpper = strtoupper($entTypeLwr);
			$tinTime = $resTaxINN["dateTin"]/1000;
			
				// //requisite_fields
			// $arReqParams = [
				// "NAME" => $resTaxINN["name"],
				// "ACTIVE" => "Y",
				// "RQ_INN" => $tin, 
				// "RQ_KPP" => "",
				// "RQ_OGRN" => "",
				// "RQ_OKVED" => $resTaxINN["nc6Code"],
				// "RQ_COMPANY_NAME" => $resTaxINN["name"],
				// "RQ_COMPANY_FULL_NAME" => $resTaxINN["nameFull"],
				// "RQ_IFNS" => "", 
				// "PRESET_ID" => $preset_id,
				// "PRESET_COUNTRY_ID" => 1,
				// "RQ_COMPANY_REG_DATE" => date("d.m.Y",$tinTime), 
				// "RQ_ADDR" => "",
				// "RQ_DIRECTOR" => $resTaxINN["gdFullName"],
				// "RQ_ACCOUNTANT" => $resTaxINN["gbFullName"],
			// ];
			
			$arReqParams = [];
			foreach($arCrmConfs["requisite"] as $rqsFields => $innField){
				if($rqsFields == "innfieldcode"){
					continue;
				}
				if(substr($innField,0,4)=="tax_"){ 
					$innField = substr($innField,4);
					$innFieldVal = $resTaxINN[$innField];
					
					if($rqsFields == "RQ_COMPANY_REG_DATE"){
						$innFieldVal = date("d.m.Y",$tinTime);
					}
					if($rqsFields == "RQ_ST_CERT_DATE"){
						$innFieldVal = date("d.m.Y",$tinTime);
					}
					$arReqParams[$rqsFields] = $innFieldVal;
				}
				
			}
			
			if(empty($arReqParams["NAME"])){
				$arReqParams["NAME"] = $resTaxINN["name"];
			}

			
			$arReqParams["ENTITY_TYPE_ID"] = $entTypes[$actEntTypeUp];
			$arReqParams["ENTITY_ID"] = $actEntId; 
			$arReqParams["PRESET_ID"] = $preset_id;
			$arReqParams["ACTIVE"] = "Y";
			$arReqParams["CODE"] = $tin;
			
			
			
			self::eLog($arReqParams,"------ ALVC :: Requisite PARAMS: ");
			
			$resReqsGtLst = BxRest::call( 'crm.requisite.list', array(
				"order"=>["DATE_CREATE"=>"DESC","ADDRESS_ONLY"=>"N"],
				"filter"=>["ENTITY_ID"=>$actEntId,"ENTITY_TYPE_ID"=>$entTypes[$entTypeUpper]]
			));
			self::eLog($resReqsGtLst,"------ ALVC :: Requisite Search RES: ");
			
			if(!empty($resReqsGtLst["result"]) && !empty($resReqsGtLst["result"][0]["ID"])){
				$resBxReqs = BxRest::call( 'crm.requisite.update', array(
					"id" => $resReqsGtLst["result"][0]["ID"], 
					"fields" =>$arReqParams
				));
			}
			else {
				$arReqParams["ENTITY_TYPE_ID"] = $entTypes[$actEntTypeUp];
				$arReqParams["ENTITY_ID"] = $actEntId; 
				
				$resBxReqs = BxRest::call( 'crm.requisite.add', array(
					"fields"=>$arReqParams
				));
			}
			
			self::eLog($arReqParams,"------ ALVC :: Requisite PARAMS: ");
			
			self::eLog($resBxReqs,"------ ALVC :: resReqs BX Upd-Adding RES: ");
			
		}
				
		
		
		return '<script src="//api.bitrix24.com/api/v1/"></script> <script> BX24.init(function(){ BX24.closeApplication(); }); </script>';
	}
	
	public function processINN($tin,$p=false){
		// $tin = "451807223"; //$resLead["result"]["UF_CRM_1622117814212"];
		$companyID = false;
		$entTypes = array(
			"LEAD" => 1,
			"DEAL" => 2,
			"CONTACT" => 3,
			"COMPANY" => 4,
			"INVOICE" => 5,
			"Quote" => 7,
			"Requisites" => 8
		);
		
		$resReqsCmnLst = BxRest::call( 'crm.company.list', array(
			"filter"=>array(
				"UTM_CONTENT" => $tin //"303903621"
			)
		));
		
		// self::eLog($resReqsCmnLst,"------ Events.php :: resCompanyLst (".$tin.") Request: ----------");
		
		if(empty($resReqsCmnLst["result"])){
			$resTaxINN = self::requesTaxInn($tin);
			
			$taxInnTxt = '';
			if(!empty($resTaxINN)){
				foreach($resTaxINN as $titxk=>$titx){
					$taxInnTxt = $taxInnTxt."".$titxk.": ".$titx."\n";
				}
			}
			
			$resINN = []; //self::innrequest($tin);
			self::eLog($resTaxINN,"------ Events.php :: TAX INN (".$tin.") Request: ----------");
			// self::eLog($resINN,"------ Events.php :: INN (".$tin.") Request: ----------");
		
			$cmpName = (!empty($resINN["shortname"])) ? $resINN["shortname"] : (!empty($resTaxINN["name"])) ? $resTaxINN["name"] : "Company_".$tin;
			$addCmpFlds = array (
				"UTM_CONTENT" => $tin,
				"TITLE" => $cmpName,
				"COMPANY_TYPE" => "CUSTOMER",
				// "EMPLOYEES" => "EMPLOYEES_2",
				// "CURRENCY_ID" => "RUB",
				// "REVENUE" => 3000000,
				//"LOGO" => { "fileData": document.getElementById('logo') },
				"OPENED" => "Y", 
				"ASSIGNED_BY_ID" => 1, 
				// "BANKING_DETAILS" => $taxInnTxt, 	
			);
			
			if(!empty($resTaxINN["nc2Name"])){
				$addCmpFlds["INDUSTRY"] = $resTaxINN["nc2Name"];
			}
			if(!empty($resTaxINN["address"])){
				$cmp_address = $resTaxINN["address"];
				if(!empty($resTaxINN["ns11Name"])){
					$cmp_address = $resTaxINN["ns11Name"].", ".$cmp_address;
				}
				if(!empty($resTaxINN["ns10Name"])){
					$cmp_address = $resTaxINN["ns10Name"].", ".$cmp_address;
				}
				$addCmpFlds["REG_ADDRESS"] = $cmp_address;
			}
			if(!empty($resTaxINN["gdTelWork"])){
				$addCmpFlds["PHONE"] = array(
					array("VALUE" => $resTaxINN["gdTelWork"], "VALUE_TYPE" => "WORK"),
					//array("VALUE" => $resTaxINN["gdTelHome"], "VALUE_TYPE" => "WORK"),
				);
			}
			if(!empty($resTaxINN["gdTelHome"])){
				$addCmpFlds["PHONE"][] = array("VALUE" => $resTaxINN["gdTelHome"], "VALUE_TYPE" => "WORK");
			}
			
			// self::eLog($addCmpFlds,"------ ALVC :: ADD COMPANY Params: ----------");
			
			$resCompanyAdd = BxRest::call( 'crm.company.add', array(
				"fields" => $addCmpFlds
			));
			
			self::eLog($resCompanyAdd,"------ ALVC :: ADD COMPANY RESULTs: ----------");
			
			if(!empty($resCompanyAdd["result"])){
				
				$resContLstCh = BxRest::call( 'crm.contact.list', array(
					"filter"=>array(
						"UTM_CONTENT" => $resTaxINN["gdTin"] 
					)
				));
				self::eLog($resContLstCh,"------ ALVC :: ADD CONT Check RES:");
				if(!empty($resTaxINN["gdTelHome"]) && empty($resContLstCh["result"])){
			
					$addContactFields = [
						"NAME" => $resTaxINN["gdFullName"],
						"OPENED" => "Y",
						"ASSIGNED_BY_ID" => 1,
						"TYPE_ID" => "CLIENT",
						"SOURCE_ID" => "SELF",
						"COMPANY_ID" => $resCompanyAdd["result"],
						"PHONE" => $addCmpFlds["PHONE"],
						"UTM_CONTENT" => $resTaxINN["gdTin"],
					];
					
					self::eLog($addContactFields,"------ ALVC :: ADD CONTACT Params...:");
					
					//crm.contact.add
					$resContactAdd = BxRest::call( 'crm.contact.add', array(
						"fields" => $addContactFields
					));
					unset($addCmpFlds["PHONE"]);
					self::eLog($resContactAdd,"------ ALVC :: ADD CONTACT RESULTs: ----------");
				}
			
			
			
				if(!empty($p)){
					$actEntType = key($p);
					$actEntId = current($p);
				}
				else{
					$actEntType = "COMPANY";
					$actEntId = $resCompanyAdd["result"];
				}
				$actParamsAdd = array(
					"OWNER_TYPE_ID" => $entTypes[$actEntType], // 1-lead  2-deal 3-contact 4-company 7-predloj 5-invoice 8-requesite
					"OWNER_ID" => $actEntId,
					"PROVIDER_ID" => 'REST_APP',
					"PROVIDER_TYPE_ID" => 'inninfo',
					"SUBJECT" => "Информация по ИНН: ".$tin. ": ".$resTaxINN["name"],
					"COMPLETED" => 'Y',
					"RESPONSIBLE_ID" => 1,
					"DESCRIPTION" => $resTaxINN["name"]." - ".$resTaxINN["address"]." - ".$resTaxINN["gdFullName"],
				);
				
				$resAct = BxRest::call( 'crm.activity.add', array( "fields"=> $actParamsAdd ));
				// self::eLog($resAct,"------ Events.php :: resAct Adding Activity:");
				
				$actCmpParamsAdd = array(
					"OWNER_TYPE_ID" => $entTypes[$actEntType],
					"OWNER_ID" => $actEntId,
					"PROVIDER_ID" => 'REST_APP',
					"PROVIDER_TYPE_ID" => 'inninfo',
					"SUBJECT" => "Новая компания: ".$resTaxINN["name"],
					"COMPLETED" => 'Y',
					"RESPONSIBLE_ID" => 1,
					"DESCRIPTION" => "https://4uz.bitrix24.ru/crm/company/details/".$resCompanyAdd["result"]."/",
				);
				
				$resAct = BxRest::call( 'crm.activity.add', array( "fields"=> $actCmpParamsAdd ));
				// self::eLog($resAct,"------ Events.php :: resAct Adding Activity:");
			}
			
			
		}
		
		$resReqsLst = BxRest::call( 'crm.requisite.list', array(
			"filter"=>array(
				"CODE" => $tin //"303903621"
			)
		));
		
		// self::eLog($resReqsLst,"------ Events.php :: resReqsLst (".$tin.") Request: ----------");
		
		
		
		if(empty($resReqsLst["result"]) && (!empty($resCompanyAdd["result"]) || !empty($resReqsCmnLst["result"][0]["ID"]))){
			if(empty($resTaxINN)){ $resTaxINN = self::requesTaxInn($tin); }
			if(empty($resINN)){ $resINN = []; } //self::innrequest($tin); }
		
			$arRqsFlds = self::getCrmFileds();
			self::eLog($arRqstFileds,"------ Events.php :: arRqstFileds FILEDS (".$tin.") Request: ----------");
			if(!empty($arRqsFlds["requisite"])){
				$arReqParams = [];
				foreach($arRqsFlds["requisite"] as $innField=>$rqsFields){
					if(substr($innField,0,4)=="tax_"){ 
						$innField = substr($innField,4);
						$innFieldVal = $resTaxINN[$innField];
					}
					else{
						$innFieldVal = $resINN[$innField];
					}
					$arReqParams[$rqsFields] = $innFieldVal;
				}
				
				if(empty($arReqParams["NAME"])){
					$arReqParams["NAME"] = $resTaxINN["name"];
				}
				// if(empty($arReqParams["NAME"])){
					// $arReqParams["NAME"] = $resINN["name"];
				// }
				
				$arReqParams["ENTITY_TYPE_ID"] = $entTypes['COMPANY']; //(!empty($resCompanyAdd["result"])) ?
				$arReqParams["ENTITY_ID"] = $companyID = (!empty($resCompanyAdd["result"])) ? $resCompanyAdd["result"] : $resReqsCmnLst["result"][0]["ID"]; 
				$arReqParams["PRESET_ID"] = (!empty($arRqsFlds["company_requesits_template"])) ? $arRqsFlds["company_requesits_template"] : 1;
				$arReqParams["ACTIVE"] = "Y";
				$arReqParams["CODE"] = $tin;
        		
				self::eLog($arReqParams,"------ ALVC :: Reqs ADD Params: ----------");
				
				$resReqsGtLst = BxRest::call( 'crm.requisite.list', array(
					"order"=>["DATE_CREATE"=>"DESC"],
					"filter"=>["ENTITY_ID"=>$companyID,"ENTITY_TYPE_ID"=>$entTypes['COMPANY']]
				));
				
				if(!empty($resReqsGtLst["result"]) && !empty($resReqsGtLst["result"][0]["ID"])){
					$resReqsAddupdating = BxRest::call( 'crm.requisite.delete', array("id" =>$resReqsGtLst["result"][0]["ID"]));
				}
				
				$resReqsAdding = BxRest::call( 'crm.requisite.add', array(
					"fields"=>$arReqParams
				));
				
				self::eLog($resReqsAdding,"------ ALVC :: resReqsAddupdating RES: ----------");
			}
			
		}
		
		return $companyID;
	}
	
	public function returnView(){
		$wrap=true;
		$req_is_admin = BxRest::call("user.admin");
		// var_dump($req_is_admin);
		$this->isAdmin = (!empty($req_is_admin["result"])) ? true : false;
		$arResult = false;
		
		if(!empty($_REQUEST["PLACEMENT"])){
			$this->eLog($_REQUEST,"-------------------== PLACEMENT ==----------------");
			$this->eLog($_SERVER,"-------------------== SERVER ==----------------");
			
			$opts = (!empty($_REQUEST['PLACEMENT_OPTIONS'])) ? json_decode($_REQUEST['PLACEMENT_OPTIONS'],true) : false;
			
			if(!empty($_SERVER["HTTP_X_REQUESTED_WITH"]) && $_REQUEST["PLACEMENT"] == "DEFAULT" && $_SERVER["HTTP_X_REQUESTED_WITH"]=="com.bitrix24.android"){
				$wrap=true;
				$arResult = $this->doUserProfileMenu();
				$loadPage = "bxplc_".$arResult['page'];
			}
			elseif($arResult = $this->placementPage($_REQUEST["PLACEMENT"],$opts)){ 
				$wrap=false;
				if(!empty($arResult['page'])){
					$loadPage = "bxplc_".$arResult['page'];
				}
			}
			elseif($_REQUEST["PLACEMENT"] == "DEFAULT"){
				$loadPage = "dashboard";
			}
		}
		elseif(!empty($_REQUEST["loadpage"])){
			$loadPage = $_REQUEST["loadpage"];
			$wrap=false;
			
		}
		
		if(!empty($loadPage)){
			if((!empty($arResult["page"])) && $arResult["page"] == 'user_profile_menu'){
					$arAlvSections = null;
					$wrap=true;
			}
			else {
				$arAlvSections = array(
					"dashboard" => array( "name" => "АлоВойс", "perms" => "all"),
					"queues" => array( "name" => "Звонки", "perms" => "all"),
					// "chdongles" => array( "name" => "GSM линии", "perms" => "admin"),
					"trunks" => array( "name" => "Линии", "perms" => "admin"),
					"peers" => array( "name" => "Внут.номера", "perms" => "admin"),
					// "stats" => array( "name" => "Статистика агентов", "perms" => "all"), 
				);
				
				if($this->isAdmin){
					$arAlvSections["soundsettings"] = array( "name" => "Записи", "perms" => "admin");
					$arAlvSections["settings"] = array( "name" => "Настройки", "perms" => "admin");
					if($this->isDevelopServer()){
						$arAlvSections["callscripts"] = array( "name" => "Скрипты звонков", "perms" => "admin");
						$arAlvSections["crmsettings"] = array( "name" => "CRM Настройки", "perms" => "admin");
						$arAlvSections["tgsettings"] = array( "name" => "Телеграм", "perms" => "admin");
					}
					if($this->isBillz()){
						$arAlvSections["billzsettings"] = array( "name" => "Billz Настройки", "perms" => "admin");
					}
					$arAlvSections["integrations"] = array( "name" => "Интеграции", "perms" => "admin");
					// $arAlvSections["tests"] = array( "name" => "Тест", "perms" => "admin");
				}
			}
			
			if(file_exists($this->rootdir."/template/".$loadPage.".php")){
				
				
				$this->eLog($loadPage,"-------------------== LoadPage: ");
				$this->eLog($wrap,"-------------------== wrap: ");
				$this->eLog($arResult,"-------------------== arResult: ");
				
				if($wrap){include($this->rootdir."/template/header.php");}
				include($this->rootdir."/template/".$loadPage.".php");
				if($wrap){include($this->rootdir."/template/footer.php");}
			}
			
			return true;
		}
		
		return false;
	}
	
	public function agentsStats(){
		$isFullPage = true;
		if(!empty($_REQUEST)){
			$this->run();
		}
		else {
			include($this->rootdir."/template/header.php");
			include($this->rootdir."/template/stats.php");
			include($this->rootdir."/template/footer.php");
		}
	}
	
	public function placementAction($opts){
		if($opts["action"] == "view_activity"){
			if(!empty($opts["activity_id"])){
				$resActivity = BxRest::call( 'crm.activity.get', array("id"=>$opts["activity_id"]) ); 
				self::eLog($resActivity,"------ Placements :: Activity GET Result: ----------");
				
				if(!empty($resActivity["result"])){
					if($resActivity["result"]["PROVIDER_TYPE_ID"] == "inninfo"){
						echo '<script src="//api.bitrix24.com/api/v1/"></script><script>BX24.closeApplication(); </script>';
						die(); //todo if error or close
					}
					
					if($resActivity["result"]["PROVIDER_TYPE_ID"] == "ecpsign"){
						if(preg_match("/\[([\d]{1,})\]/",$resActivity["result"]["DESCRIPTION"],$arId)){
							if(!empty($arId[1])){
								$resDocument = BxRest::call( 'crm.documentgenerator.document.list', array("filter"=>array("id"=>$arId[1])) ); 
								self::eLog($resDocument,"------ Placements :: Document GET Result: ----------");
								echo "<PRE>"; var_dump($resDocument); echo "</PRE>";
							}
						}
						elseif(preg_match("/id=([\d]{1,})/",$resActivity["result"]["DESCRIPTION"],$arId)){
							if(!empty($arId[1])){
								$resDocument = BxRest::call( 'crm.documentgenerator.document.list', array("filter"=>array("id"=>$arId[1])) ); 
								self::eLog($resDocument,"------ Placements :: Document GET Result: ----------");
								if(!empty($resDocument["result"]["documents"])){
									$GLOBALS["document"] = $resDocument["result"]["documents"][0];
									return  ['page' => "action_documentpage"];
								}
								
							}
						}
					}
				}
				
				// echo "<PRE>"; var_dump($resActivity); echo "</PRE>";
			}
		}
		else {
			return json_encode($opts);
		}
	}
	
	public function entityTelegramCheck($plc,$opts){
		$arPlcName = explode("_",$plc);
		$entity = $arPlcName[1];
		$entity_id = strtolower($opts["ID"]);
		$resEntity = BxRest::call( 'crm.'.$entity.'.get', array("id"=>$entity_id) ); 
		self::eLog($resEntity,"------ Placements :: Entity GET Result: ----------");
		
		if(!empty($resEntity["result"])){
			// $GLOBALS["datas"] = $resEntity["result"];
			
			if(!empty($resEntity["result"]["IM"])){
				foreach($resEntity["result"]["IM"] as $imol){
					if(preg_match("/alotg/",$imol["VALUE"])){
						echo '<script src="//api.bitrix24.com/api/v1/"></script><script>BX24.closeApplication(); </script>';
						die(); //todo if error or close
					}
				}
			}

			
			$numbers = [];
			$crmPhones = [];
			if(!empty($resEntity["result"]["PHONE"])){
				
				foreach($resEntity["result"]["PHONE"] as $arphone){
					$phone = preg_replace("/[^0-9]/", '', $arphone["VALUE"]);
					if(strlen($phone)==9){
						$phone = '998'.$phone;
					}
					
					if(strlen($phone)>9){
						$numbers[] = $phone;
						$arphone["VALUE"] = '+'.$phone;
					}
					
					$crmPhones[] = $arphone;
					
					
				}
			}

			if(!empty($numbers)){
				$TG = new \TGA\ATelegram();
				$alvRest = new AloVoiceRest($this->configs);
		
				foreach($numbers as $num){
					$tgRes = $TG->add_tgimol($num);
					self::eLog($tgRes,"------========= ALVC :: TG Phone Contact Validate:");
					
					if(!empty($tgRes["action"])){
						
						if(!empty($crmPhones)){
							//$crmPhones
							$resUpdEntity = BxRest::call( 'crm.'.$entity.'.update', array(
								"id" => $entity_id,
								"fields" => [ "PHONE" => $crmPhones ]
							) ); 
							
							self::eLog($resUpdEntity,"------========= ALVC :: IMADD CRM Ent Update RES:");
						}
						
						
						$resAction = $alvRest->alovoice_incom_message($tgRes["action"]);
						self::eLog($resAction,"------========= ALVC :: IMADD Action RES:");
						
						
						return  ['page' => "crm_activity_tgpage"];
					}
					else {
						echo '<script src="//api.bitrix24.com/api/v1/"></script><script>BX24.closeApplication(); </script>';
						die(); //todo if error or close
					}
					
				}
			}
			
			
		}
		
		$GLOBALS["infos"] = $_REQUEST;
		return  ['page' => "errors_page"];
	}
	
	public function placementPage($plc,$opts){
		
		
		if(!empty($opts["action"])){
			return $this->placementAction($opts);
		}
		
		if(isset($_REQUEST["tgupd"])){
			return $this->entityTelegramCheck($plc,$opts);
		}
		if(isset($_REQUEST["inncheck"])){
			return $this->inncheck($plc,$opts);
		}
			
		if($plc == 'CALL_CARD'){
			return $this->callcard_check();
		}
		$opts = json_decode($_REQUEST['PLACEMENT_OPTIONS'],true);
		if($plc == 'USER_PROFILE_MENU'){
			return $this->doUserProfileMenu();
		}
		if($plc == 'SETTING_CONNECTOR'){
			return $this->openlineActivation();
		}
		
		if($plc == 'CRM_DEAL_LIST_MENU'){
			return ['page' => "crm_deal_list_menu"];
		}
		
		if($plc == 'CRM_DEAL_ACTIVITY_TIMELINE_MENU' || $plc == 'CRM_DEAL_DOCUMENTGENERATOR_BUTTON'){
			return ['page' => "didox"];
		}
		
		if( in_array($plc,[
			"CRM_LEAD_DETAIL_ACTIVITY",
			"CRM_LEAD_DETAIL_ACTIVITY",
			"CRM_DEAL_DETAIL_ACTIVITY",
			"CRM_CONTACT_DETAIL_ACTIVITY",
			"CRM_COMPANY_DETAIL_ACTIVITY",
			"CRM_LEAD_DETAIL_TAB",
			"CRM_DEAL_DETAIL_TAB",
			"CRM_CONTACT_DETAIL_TAB",
			"CRM_COMPANY_DETAIL_TAB",
			'CRM_DEAL_LIST_MENU'
			])
		){
			
			$strPlct = $_REQUEST['PLACEMENT'];
			$arPlcnt = explode("_",$strPlct);
			$entityUp = $arPlcnt[1];
			$entity = strtolower($entityUp);
			$opts = json_decode($_REQUEST['PLACEMENT_OPTIONS'],true);
			if(!empty($opts["ID"])){
				$entID = $opts["ID"];
				$resEntity = BxRest::call( 'crm.'.$entity.'.get', array("id"=>$entID) ); 
				self::eLog($resEntity,"------ Placements :: Entity GET Result: ----------");
				
				if(!empty($resEntity["result"]["ID"]) && !empty($resEntity["result"]["UF_CRM_1622117814212"])){
					$tin = $resEntity["result"]["UF_CRM_1622117814212"];
				}
				
				if(!empty($tin)){
					// $tgres = ALVC::checkTgContact($resLead["result"]);
					//$cid = ALVC::processINN($tin,["LEAD"=>$leadID]);
					// $cid = ALVC::importByINN($tin,[$entityUp=>$entID]);
					$this->importByINN($tin,[$entityUp=>$entID]);
				}
			}
			else{
				self::eLog($opts,"------ Placements :: Мало данных:: ----------");
				return "Мало данных: ".$_REQUEST['PLACEMENT_OPTIONS'];
			}
			// echo '<PRE>'; var_dump($_REQUEST); echo '</PRE>';
			return  ['page' => "crm_activity_form"];
			
		}
		
		return false;
	}
	
	public function doUserProfileMenu(){
		
		if(empty($_REQUEST["PLACEMENT_OPTIONS"])){
			return ['page'=>'user_profile_menu',"body"=>"Нет параметров"];
		}
		
		$arOpts = json_decode($_REQUEST["PLACEMENT_OPTIONS"],true);
		
		// if(empty($arOpts) || empty($arOpts["USER_ID"])){
			// return ['page'=>'user_profile_menu',"body"=>"Сотрудник или номер не найден"];
		// }
		
		// return ['page'=>'user_profile_menu',"body"=>$arOpts["USER_ID"]];
		if(!empty($arOpts["USER_ID"])){
			$gotUser = BxRest::call('user.get',[ 'ID' => $arOpts["USER_ID"] ]);
			if(!empty($gotUser["result"])){ $arUser = $gotUser["result"][0]; }
		}
		if(empty($arUser)){
			$gotUser = BxRest::call("user.current");
			if(!empty($gotUser["result"])){ $arUser = $gotUser["result"]; }
		}
		
		if(empty($arUser)){
			return ['page'=>'user_profile_menu',"body"=>"Сотрудник или номер не найден"];
		}

		if(empty($arUser["UF_PHONE_INNER"])){
			return ['page'=>'user_profile_menu',"body"=>"Нету номера"];
		}
		$num = $arUser["UF_PHONE_INNER"];
		
		// if($num=="2424"){
			// $num = "3031";
		// }
		
		if($num=="2424"){
			$arSoftphone = self::getUserSoftphoneExe($num);
		}
		else{
			$arSoftphone = self::getUserSoftphoneExe($num);
			// $arSoftphone = self::getUserSoftphone($num);
		}
		
		$arResult = ['page'=>'user_profile_menu'];
		$arResult['header'] = 'Программа для звонков в Windows';
		$arResult['body'] = '';
		// var_dump($arSoftphone);
		if(!empty($arSoftphone["link"])){
			if($num=="2424"){
				// var_dump($arSoftphone);
			}
			$arResult['link'] = $arSoftphone["link"];
			$arResult['qrpng'] = $arSoftphone["qrpng"];
			$arResult['password'] = $arSoftphone["password"];
			$arResult['number'] = $num;
		}
		else{
			$arResult['body'] .= '<br>Чтото пошло не так, попробуйте позже, скажем через часик...<br>'.json_encode($arSoftphone);
		}
		
		// $arResult['body'] .= '<br>test: '.json_encode($arSoftphone) ;
		
		return $arResult;
	}
	
	public function callcard_check(){
		$arResult = ['page'=>'call_card'];
		$placeOptions = json_decode($_REQUEST["PLACEMENT_OPTIONS"],true);
		if(empty($placeOptions["CRM_ENTITY_TYPE"])){
			// $resUserInfo = BxRest::call("user.get",array(
				// 'PERSONAL_MOBILE' => $placeOptions["PHONE_NUMBER"]
			// ));
			// $this->eLog($resUserInfo,"--== resUserInfo SEARCH STAFFS on BITRIX");
		}
		if(!empty($resUserInfo['result'])){
			$arResult['body'] = 
				'<center><h2>Звонок от сотрудника: '
				.$resUserInfo['result'][0]["NAME"].' 	'
				.$resUserInfo['result'][0]["LAST_NAME"]
				.'</h2></center><br><center><img src="'
				.$resUserInfo['result'][0]["PERSONAL_PHOTO"]
				.'" style="    width: 30%;"/></center>';
		} else {
			$artgInfo = "";//$this->TG->get_contact_info($placeOptions["PHONE_NUMBER"]);
			// $this->eLog($artgInfo,"--== get_contact_info on TG");
			
			$arrGoogleInfo = ""; //json_encode(self::requestGoogle($placeOptions["PHONE_NUMBER"]));
			// $this->eLog($artgInfo,"--== requestGoogle on GOOGLE");
			
			
			$resHTML = ''; //'<h2>В телеграме:</h2>';
			$resHTML .= '<div class="tginfo">'.$artgInfo.'</div>';
			// $resHTML .= '<h2>В Google:</h2>';
			$resHTML .= '<div class="googleinfo">'.$arrGoogleInfo.'</div>';
			
			
			$arResult['body'] = $resHTML;
		}
		
		return $arResult;
	}
	
	public function getSoundsPath($configs=false){
		if(empty($configs)){ $configs = self::getConfigs(); }
		$sDir = $configs["basedir"].'/'.$configs["sounds_folder"];
		if(!is_dir($sDir)){ mkdir($sDir,0777); }
		return $sDir;
	}
	
	public function getUserSoftphone($num){
		$configs = self::getConfigs();
		$title = $configs["bitrix_domain"];
		
		$ip = (!empty($configs["sipaddress_local"])) ? $configs["sipaddress_local"] : '192.168.123.6';
		$port = (!empty($configs["sipport_local"])) ? $configs["sipport_local"] : '5060';
		
		$out_ip = (!empty($configs["sipaddress_out"])) ? $configs["sipaddress_out"] : '192.168.123.6';
		$out_port = (!empty($configs["sipport_out"])) ? $configs["sipport_out"] : '5060';

		
		$bxaddr = 'https://'.$configs["bitrix_domain"];
		
		$alvActions = new AloVoiceActions($configs);
		$passPeer = $alvActions->getPeerPassword($num);
		if(empty($passPeer)){
			return false; //["result"=>"Не удалось получить пароль на номер:".$num];
		}
		
		$sampleSoftfoneDir = $configs["basedir"].'/amibx_install/softphone/';
		$alvFilesDir = $configs["basedir"].'/files/';
		$newUseSoftfoneDir = $alvFilesDir.'sphone_'.$num;
		$newUseSoftfoneZip = $alvFilesDir.'sphone_'.$num.'.zip';
		$newUseSoftfoneLink = $configs["alovoice_host"].'files/sphone_'.$num.'.zip';
		
		$newUserSftSipperFile = $newUseSoftfoneDir.'/sipper.ini';
		$newUserSftProviderFile = $newUseSoftfoneDir.'/provider.ini';
		
		if(file_exists($newUseSoftfoneZip)){
			return ["link"=>$newUseSoftfoneLink];
		}
		
		if(!file_exists($newUseSoftfoneDir)){
			$mkdirRes = mkdir($newUseSoftfoneDir,0777);
			if(self::recurse_copy($sampleSoftfoneDir,$newUseSoftfoneDir)){
				
				$sipperPutRes = file_put_contents( $newUserSftSipperFile, self::make_sipperini($ip,$port,$out_ip,$out_port,$num,$passPeer) );
				$providerPutRes = file_put_contents( $newUserSftProviderFile, self::make_providerini($title,$ip,$bxaddr) );
			}
			
			$zipRes = exec('cd '.$alvFilesDir.' && /usr/bin/zip -r sphone_'.$num.'.zip sphone_'.$num);
			//$newUseSoftfoneDir
			
			$res = [$title,$ip,$bxaddr,$port,$num,$passPeer,$newUseSoftfoneDir,$mkdirRes,$copyRes,$sipperPutRes,$providerPutRes,"zipres"=>$zipRes,"link"=>$newUseSoftfoneLink];
		}
		else{
			$res = ["result"=>"Directory Ready","dir"=>$newUseSoftfoneDir];
		}
		
		
		return $res;
		// $provider_init = self::make_providerini($title,$ip,$bxaddr);
		// $sipper_init = self::make_sipperini($ip,$port,$num,$pass);
	}
	
	public function getUserSoftphoneExe($num){
		$configs = self::getConfigs();
		$title = $configs["bitrix_domain"];
		
		$ip = (!empty($configs["sipaddress_local"])) ? $configs["sipaddress_local"] : '192.168.123.6';
		$port = (!empty($configs["sipport_local"])) ? $configs["sipport_local"] : '5060';
		
		$out_ip = (!empty($configs["sipaddress_out"])) ? $configs["sipaddress_out"] : '192.168.123.6';
		$out_port = (!empty($configs["sipport_out"])) ? $configs["sipport_out"] : '5060';

		
		$bxaddr = 'https://'.$configs["bitrix_domain"];
		
		$alvActions = new AloVoiceActions($configs);
		$passPeer = $alvActions->getPeerPassword($num);
		if(empty($passPeer)){
			return ["result"=>"Не удалось получить пароль на номер:".$num];
		}
		
		$sampleSoftfoneExeMaker = $configs["basedir"].'/alovoice/exemaker.sh';
		$sampleSoftfoneExe = $configs["basedir"].'/alovoice/phonerlite.exe';
		$newUseSoftfoneDir = $configs["basedir"].'/files/phonerlite_'.$num.'/';
		if(!file_exists($newUseSoftfoneDir)){
			mkdir($newUseSoftfoneDir,0777);
		}
		
		$softfoneUserExe = $newUseSoftfoneDir.'phonerlite.exe';
		$newUseSoftfoneLink = $configs["alovoice_host"].'files/phonerlite_'.$num.'/phonerlite.exe';
		
		$qrPng = self::make_qraccount($configs,$out_ip.":".$out_port,$num,$passPeer);
		
		if(file_exists($softfoneUserExe)){
			return ["link"=>$newUseSoftfoneLink,"qrpng"=>$qrPng,"password"=>$passPeer];
		}
		
		$newUserSftSipperFile = $newUseSoftfoneDir.'sipper.ini';
		$newUserSftProviderFile = $newUseSoftfoneDir.'provider.ini';
		
		
		
		$sipperPutRes = file_put_contents( $newUserSftSipperFile, self::make_sipperini($ip,$port,$out_ip,$out_port,$num,$passPeer) );
		$providerPutRes = file_put_contents( $newUserSftProviderFile, self::make_providerini($title,$ip,$bxaddr) );
		
		if(file_exists($sampleSoftfoneExe)){
			copy($sampleSoftfoneExe,$softfoneUserExe);
			$exeChRes = exec($sampleSoftfoneExeMaker.' '.$softfoneUserExe.' '.$newUserSftSipperFile);
			$exeChPrRes = exec($sampleSoftfoneExeMaker.' '.$softfoneUserExe.' '.$newUserSftProviderFile);
			
			
			$res = [$title,$ip,$bxaddr,$port,$num,$passPeer,$newUseSoftfoneDir,$sipperPutRes,$providerPutRes,"qrpng"=>$qrPng,"exeChRes"=>$exeChRes,"exeChPrRes"=>$exeChPrRes,"link"=>$newUseSoftfoneLink,"password"=>$passPeer];
		}
		else{
			$res = ["result"=>"Directory Ready","dir"=>$sampleSoftfoneExe,"isSample"=>file_exists($sampleSoftfoneExe),"password"=>$passPeer];
		}
		
		
		return $res;
		// $provider_init = self::make_providerini($title,$ip,$bxaddr);
		// $sipper_init = self::make_sipperini($ip,$port,$num,$pass);
	}
	
	public function make_qraccount($configs,$domain,$num,$pass){
		$fpath = dirname(dirname(dirname(__DIR__)))."/".$configs["files_folder"];
		$filename = 'qr_'.md5($num.'_'.$pass).'.png';
		$file = $fpath.$filename;
		$pngLink =$configs["alovoice_host"]."files/".$filename;
		
		if(file_exists($file)){
			return $pngLink;
		}
		
		$strQR = '<?xml version="1.0" encoding="utf-8"?>'
			.'<AccountConfig version="1"><Account>'
				.'<RegisterServer>'.$domain.'</RegisterServer>'
				.'<UserID>'.$num.'</UserID>'
				.'<AuthID>'.$num.'</AuthID>'
				.'<AuthPass>'.$pass.'</AuthPass>'
				.'<AccountName>'.$num.'</AccountName>'
				.'<DisplayName>TUG_'.$num.'</DisplayName>'
				.'<Voicemail>*97</Voicemail>'
			.'</Account></AccountConfig>';

		QRcode::png($strQR, $file, 2, 3, 4, true);
		
		return $pngLink;
	}
	
	public function make_providerini($title,$ip,$addr){
		$iniText = '['.$title.']
Registrar='.$ip.'
Realm='.$ip.'
Codecs=9,-107,8,0,-2,-3,-97,-110,-111,18,-112,-113,-114,101,-11,-118
URL='.$addr;
		return $iniText;
	}
	
	public function make_sipperini($addr,$port='5060',$addr_out,$port_out='5060',$num,$pass){
		if($port!='5060'){
			$addr_out = $addr_out.':'.$port;
		}
		$iniText = '[Profile]
Profile=Alovoice_'.$num.'

[Alovoice_'.$num.']
UserName='.$num.'|'.$num.'
DisplayName=Technounit
Password='.$pass.'
LocalPort='.$port_out.'
Gateway='.$addr_out.'
STUN=
Realm='.$addr_out.'
Register=1
Codecs=9,-107,8,0,-2,-3,-97,-110,-111,18,-112,-113,-114,101,-11,-118
UseAppGUID=1
AppGUID=00DE6AE6-4E26-EB11-ACBB-6D762EC99F4D
Mailbox=
PhoneNumber=
MWI=1
RegisterPeriod=600
ConnectionType=0
NoFallback=0
Alias=0
SessionTimers=0
MDNS=1
MDNS_sipuri=0
UPnP=0
ResolveDefaultGateway=1
IPv6=0
DualStackIPv6=0
QoS=1
GRUU=1
CheckUsername=1
CheckFirewall=0
MirrorRTP=0
ForceOwnCodecPriority=0
ForceOldCodecPriority=0
AllowAutoAnswer=0
SendEmptyInvite=0
PEarlyMedia=0
SendRingbackTone=0
EchoTail=100
EchoOffset=60
SpeexBandwidth=15
ENUM=e164.org, e164.arpa, e164.info
SRTP=0
UNENCRYPTED_SRTCP=0
UNAUTHENTICATED_SRTP=0
MediaSec=0
ZRTP=0
ZRTP_MASQUERADE=0
SAVP=0
MOH=2
G726_AAL2=1
G722_16000=0
Silence=0
ServerCertificate=
ServerKey=
ClientCertificate=
CheckCertificate=0
LoadWindowsCA=0
AGC_in=0
AGC_out=0
Denoise_in=0
Denoise_out=1
NoiseSuppress_in=15
NoiseSuppress_out=15
DeclineNotBusy=0
RTPoverSIPFallback=5
RTP_auto_STUN=0
STUNoverSIP=0
DoOverrideIP=1
DelayedHoldRetrieve=0
IgnoreDomainForIncomingCalls=0
BNC=0
FetchBindings=0
HTTP=1
ActivationCount=28
CFU=';
		return $iniText;
	}
	
	public function OLD_make_sipperini($addr,$port='5060',$addr_out,$port_out='5060',$num,$pass){
		$iniText = '[Profile]
Profile=Alovoice_'.$num.'

[Office_local_'.$num.']
UserName='.$num.'|'.$num.'
DisplayName=Technounit
Password='.$pass.'
LocalPort='.$port.'
Gateway='.$addr.'
STUN=
Realm='.$addr.'
Register=1
Codecs=9,-107,8,0,-2,-3,-97,-110,-111,18,-112,-113,-114,101,-11,-118
UseAppGUID=1
AppGUID=00DE6AE6-4E26-EB11-ACBB-6D762EC99F4D
Mailbox=
PhoneNumber=
MWI=1
RegisterPeriod=600
ConnectionType=0
NoFallback=0
Alias=0
SessionTimers=0
MDNS=1
MDNS_sipuri=0
UPnP=0
ResolveDefaultGateway=1
IPv6=0
DualStackIPv6=0
QoS=1
GRUU=1
CheckUsername=1
CheckFirewall=0
MirrorRTP=0
ForceOwnCodecPriority=0
ForceOldCodecPriority=0
AllowAutoAnswer=0
SendEmptyInvite=0
PEarlyMedia=0
SendRingbackTone=0
EchoTail=100
EchoOffset=60
SpeexBandwidth=15
ENUM=e164.org, e164.arpa, e164.info
SRTP=0
UNENCRYPTED_SRTCP=0
UNAUTHENTICATED_SRTP=0
MediaSec=0
ZRTP=0
ZRTP_MASQUERADE=0
SAVP=0
MOH=2
G726_AAL2=1
G722_16000=0
Silence=0
ServerCertificate=
ServerKey=
ClientCertificate=
CheckCertificate=0
LoadWindowsCA=0
AGC_in=0
AGC_out=0
Denoise_in=0
Denoise_out=1
NoiseSuppress_in=15
NoiseSuppress_out=15
DeclineNotBusy=0
RTPoverSIPFallback=5
RTP_auto_STUN=0
STUNoverSIP=0
DoOverrideIP=1
DelayedHoldRetrieve=0
IgnoreDomainForIncomingCalls=0
BNC=0
FetchBindings=0
HTTP=1
ActivationCount=28
CFU=

[Office_out_'.$num.']
UserName='.$num.'|'.$num.'
DisplayName=Technounit
Password='.$pass.'
LocalPort='.$port_out.'
Gateway='.$addr_out.'
STUN=
Realm='.$addr_out.'
Register=1
Codecs=9,-107,8,0,-2,-3,-97,-110,-111,18,-112,-113,-114,101,-11,-118
UseAppGUID=1
AppGUID=00DE6AE6-4E26-EB11-ACBB-6D762EC99F4D
Mailbox=
PhoneNumber=
MWI=1
RegisterPeriod=600
ConnectionType=0
NoFallback=0
Alias=0
SessionTimers=0
MDNS=1
MDNS_sipuri=0
UPnP=0
ResolveDefaultGateway=1
IPv6=0
DualStackIPv6=0
QoS=1
GRUU=1
CheckUsername=1
CheckFirewall=0
MirrorRTP=0
ForceOwnCodecPriority=0
ForceOldCodecPriority=0
AllowAutoAnswer=0
SendEmptyInvite=0
PEarlyMedia=0
SendRingbackTone=0
EchoTail=100
EchoOffset=60
SpeexBandwidth=15
ENUM=e164.org, e164.arpa, e164.info
SRTP=0
UNENCRYPTED_SRTCP=0
UNAUTHENTICATED_SRTP=0
MediaSec=0
ZRTP=0
ZRTP_MASQUERADE=0
SAVP=0
MOH=2
G726_AAL2=1
G722_16000=0
Silence=0
ServerCertificate=
ServerKey=
ClientCertificate=
CheckCertificate=0
LoadWindowsCA=0
AGC_in=0
AGC_out=0
Denoise_in=0
Denoise_out=1
NoiseSuppress_in=15
NoiseSuppress_out=15
DeclineNotBusy=0
RTPoverSIPFallback=5
RTP_auto_STUN=0
STUNoverSIP=0
DoOverrideIP=1
DelayedHoldRetrieve=0
IgnoreDomainForIncomingCalls=0
BNC=0
FetchBindings=0
HTTP=1
ActivationCount=28
CFU=';
		return $iniText;
	}
	
	public function recurse_copy($src,$dst) { 
		$dir = opendir($src); 
		@mkdir($dst); 
		while(false !== ( $file = readdir($dir)) ) { 
			if (( $file != '.' ) && ( $file != '..' )) { 
				if ( is_dir($src . '/' . $file) ) { 
					self::recurse_copy($src . '/' . $file,$dst . '/' . $file); 
				} 
				else { 
					copy($src . '/' . $file,$dst . '/' . $file); 
				} 
			} 
		} 
		closedir($dir); 
		
		return true;
	} 

	public function requestGoogle($query){
		//$qry = '7472527';
		$cx = '012992974389061153904:o5wjob1zg7g';
		$gkey = 'AIzaSyD4Zvj6d8yndsBzhJV4HXUs6ABsWfSeClg';
		$url = "https://www.googleapis.com/customsearch/v1?key=".$gkey."&cx=".$cx."&q=".$query; //
		//$url = "https://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=Kuldash%20Navruzov&userip=192.168.0.12";
		$ch = curl_init();
		//<script async src="https://cse.google.com/cse.js?cx=012992974389061153904:o5wjob1zg7g"></script>
	
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_REFERER, 'https://4u.uz');
		curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1');
		
		$body = curl_exec($ch);
		
		curl_close($ch);
		return (!empty($body["items"])) ? json_decode($body["items"],true) : [];
	}
	
	public function openlineActivation(){
		$arResult = ['page'=>'setting_connector'];
		//OpenLine Activation
		$this->eLog($_REQUEST,"-------------------==OPENLINE ACTIVATION ==----------------");
		if (!empty($_REQUEST['PLACEMENT_OPTIONS'])) {
			//activate connector
			$accInfo = $this->TG->get_tg_account_self();
			
			if(empty($accInfo)){ 
				$arResult['body'] = 'Аккaунт телеграма не настроена. Пройдите пожалуйста к настройкам телеграм акконута в приложении "AloVoice"'; 
				return $arResult;
			} else {
				$arResult['info'] = $accInfo;
			}
			
			$options = json_decode($_REQUEST['PLACEMENT_OPTIONS'], true);
			
			if(empty($options['REGISTER_STATUS'])){

			}
			
			$oLine = $this->TG->getLine();
			$connrID = $this->TG->getCode();
			$widgetUri = $this->configs["alovoice_host"];
			$widgetName = 'Telegram Клиент';
			//{"CONNECTOR":"tgclient998971041030","LINE":"1","STATUS":false,"ACTIVE_STATUS":true,"CONNECTION_STATUS":false,"REGISTER_STATUS":false,"ERROR_STATUS":false}
			if( !empty($options['LINE']) ){
				$result = BxRest::call( 'imconnector.activate', [
					'CONNECTOR' => $connrID,
					'LINE' => intVal($options['LINE']),
					'ACTIVE' => intVal($options['ACTIVE_STATUS']),
				]);
				$this->eLog($result,"-------------------== imconnector.activate REST RES ==----------------");
				
				if(!empty($result["result"])){
					$resultWidgetData = BxRest::call( 'imconnector.connector.data.set', [
						'CONNECTOR' => $connrID,
						'LINE' => intVal($options['LINE']),
						'DATA' => [
							'id' => $connrID.'line'.intVal($options['LINE']),
							'url_im' => $widgetUri,
							'name' => $widgetName
						],
					]);
					if(!empty($resultWidgetData['result'])) {
						$this->eLog($resultWidgetData,"-------------------== imconnector.connector.data.set REST RES ==----------------");
					}
				}
			}
			
			if( (empty($options['ACTIVE_STATUS'])) || (empty($oLine)) || (intval($oLine) != intval($options['LINE'])) ){
				$result = BxRest::call( 'imconnector.activate', [
					'CONNECTOR' => $connrID,
					'LINE' => intVal($options['LINE']),
					'ACTIVE' => intVal($options['ACTIVE_STATUS']),
				]);
				$this->eLog($result,"-------------------== imconnector.activate REST RES ==----------------");
			}
			
			
			
			if( !empty($oLine) && intval($oLine) == intval($options['LINE']) ){
				//$arResult['body'] = 'successfully';
				$arResult['body'] = 'Линия подключён к акaунту Телеграм: <br> <b>'.$accInfo->print_name.'</b> ('.$accInfo->phone.') <pre>['.$accInfo->username.']</pre>';
				
			}
				
			elseif( empty($oLine) || $oLine != $options['LINE'] ){
				if (!empty($result['result'])) {
					$this->TG->setLine($options['LINE']);
					$arResult['body'] = 'Линия успешно подключён к аккaунту Телеграм: <br> <b>'.$accInfo->print_name.'</b> ('.$accInfo->phone.') <pre>@['.$accInfo->username.']</pre>';
				} 
			}
			
			else {
				$arResult['body'] = 'Не подключился!';
			}
			
			return $arResult;
			
		}
	}
	
	
	
	public function returnDump($res){
		echo '<PRE>'; var_dump( $res ); echo '</PRE>'; 
		return true;
	}
	
	public function returnRes($res){
		echo (is_array($res)) ? json_encode($res) : $res;
		return true;
	}
	public function returnError($err){
		echo '<span style="padding:10px; border:1px solid #f00; color:#f00;">';
		echo (is_array($err)) ? json_encode($err) : $err;
		echo '</span>';
		return true;
	}
	

	public function makeQR($text,$file=false){
		if(empty($text)){
			return '';
		}
		
		if(empty($file)){
			$this->files = $this->rootdir."/".$this->configs["files_folder"];
			$file = $this->files.'qrcode_'.time().'.png';
		}
		$pngLink = $this->configs["alovoice_host"]."files/".basename($file);
		$resPng = QRcode::png($text, $file, 2, 3, 4, true);
		$logopath = $this->files.'tug_logo_mini.png';
		$QR = imagecreatefrompng($filepath);

		// START TO DRAW THE IMAGE ON THE QR CODE
		$logo = imagecreatefromstring(file_get_contents($logopath));
		$QR_width = imagesx($QR);
		$QR_height = imagesy($QR);

		$logo_width = imagesx($logo);
		$logo_height = imagesy($logo);

		// Scale logo to fit in the QR Code
		$logo_qr_width = $QR_width/3;
		$scale = $logo_width/$logo_qr_width;
		$logo_qr_height = $logo_height/$scale;

		imagecopyresampled($QR, $logo, $QR_width/3, $QR_height/3, 0, 0, $logo_qr_width, $logo_qr_height, $logo_width, $logo_height);

		// Save QR code again, but with logo on it
		imagepng($QR,$filepath);

		return $pngLink;
	}
	
	public function registration(){
		//echo "Uraaaaa registration!!!!!";
		
		$qrCode = (!empty($_REQUEST["qrcode"])) ? $_REQUEST["qrcode"] : false;
		$regNum = (!empty($_REQUEST["reg"])) ? $_REQUEST["reg"] : false;
		
		if(!empty($qrCode)){
			$qrTxt = base64_decode($qrCode);
			return QRcode::png('https://bx.4u.uz/reg'.$qrTxt);
		}
		elseif(is_numeric($regNum)){
			$arReg = BxRest::call("crm.deal.update",array("id"=>$regNum,"fields"=>array("STAGE_ID"=>"C6:1")));
			// $arReg = BitrixRest::call("crm.deal.update",array("id"=>$regNum,"fields"=>array("STAGE_ID"=>"C6:1")));
			if($arReg["result"]){ echo "OK";}
		}
		/*echo '<hr><PRE>';
		var_dump($arReg);
		
		echo '</PRE>';*/
		//return QRcode::png('https://bx.4u.uz/dl173');
		}


	public function goConfigurePage(){
		$bxDomain = (!empty($_REQUEST["DOMAIN"])) ? $_REQUEST["DOMAIN"] : ''; //parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST);
		if((empty($bxDomain)) && (!empty($_REQUEST['domain']))) { $bxDomain = $_REQUEST['domain']; }
		
		$access_token = (!empty($_REQUEST['AUTH_ID'])) ? $_REQUEST['AUTH_ID'] : '';
		if((empty($access_token)) && (!empty($_REQUEST['access_token']))) { $access_token = $_REQUEST['access_token']; }
		
		$refresh_token = (!empty($_REQUEST['REFRESH_ID'])) ? $_REQUEST['REFRESH_ID'] : '';
		if((empty($refresh_token)) && (!empty($_REQUEST['refresh_token']))) { $refresh_token = $_REQUEST['refresh_token']; }
		
		$application_token = (!empty($_REQUEST['APP_SID'])) ? $_REQUEST['APP_SID'] : '';
		if((empty($application_token)) && (!empty($_REQUEST['application_token']))) { $application_token = $_REQUEST['application_token']; }
		
		$expires_in = (!empty($_REQUEST['AUTH_EXPIRES'])) ? $_REQUEST['AUTH_EXPIRES'] : '';
		if((empty($expires_in)) && (!empty($_REQUEST['expires_in']))) { $expires_in = $_REQUEST['expires_in']; }
		
		$member_id = (!empty($_REQUEST['member_id'])) ? $_REQUEST['member_id'] : '';
		$ami_user = (!empty($_REQUEST['ami_user'])) ? $_REQUEST['ami_user'] : '';
		$ami_pass = (!empty($_REQUEST['ami_pass'])) ? $_REQUEST['ami_pass'] : '';

		include($this->rootdir."/template/configure.php");
		
		return false;
	}
	
	// public function run_OLD(){
	
		// $this->eLog($_REQUEST,"------ AloVoiceConnector: RUN ----------");
		// $alvActions = new AloVoiceActions($this->configs);
		// if($resAction = $alvActions::doAction()){
			// return $this->returnRes($resAction);
		// }
		
		// $this->doAuth();
		
		// $this->eLog("------ AloVoiceConnector: AUTH DONE ----------");
		
		// if(!$this->bitrixHandle()){
			// $this->eLog("No Bitrix Handle...");
		// } else {
			// //$this->eLog($_REQUEST,"------ Bitrix Handle ----------");
			// return true; 
		// }
	
		// if(BitrixRest::isListenCalls()){
			// if($_SESSION["is_admin"]){
				// return $this->mainAction();
			// } else {
				// return $this->mainStaffAction();
			// }
		// }
	// }
	
	// public function mainStaffAction(){
		// include($this->rootdir."/template/usermain.php");
	// }
	
	// public function mainAction(){
		// self::eLog("Events: ");
		// include($this->rootdir."/template/wellcome.php");
		
		// return true;
		// //$arPlacements = BitrixRest::call("placement.get");
		
		// //$this->eLog($arPlacements,"arPlacements");
		
		
		
		// $actions = new AloVoiceActions($this->configs);
		// //$actions = new AloVoiceActions($this->config);
		// $arResult = array("arPeers" => $actions->getPeersList());
		// $arStaffs = BitrixRest::call("user.get");
		
		// //var_dump($arResult["arPeers"]);
		// //var_dump("<hr>");
		
		// //var_dump($arStaffs["result"]);
		// //var_dump("<hr>");
			
		// $staffsList = array();
		// $arStaffsNumbers = array();
		// foreach( $arStaffs["result"] as $stf ){
			
			// $stNum = (!empty($stf["UF_PHONE_INNER"])) ? $stf["UF_PHONE_INNER"] : false;
			// if(empty($stNum) && (!empty($stf["WORK_PHONE"]))){ $stNum  = $stf["WORK_PHONE"]; }
			// if(!empty($stNum)){
				// $stNum = (int)$stNum;
				// //var_dump($stNum);  
				// if( !empty($arResult["arPeers"][$stNum]) ){
					// $stf["peer"] = $arResult["arPeers"][$stNum];
					// $arStaffsNumbers[$stNum] = $stf;
					// unset($arResult["arPeers"][$stNum]);
				// } else {
					
					// $staffsList[] = $stf;
				// }
				// //var_dump("<hr>");
			// } else {
				// $staffsList[] = $stf;
			// }
		// }
		// //var_dump($arStaffsNumbers);
		// $arResult["arStaffsNumbers"] = $arStaffsNumbers;
		// $arResult["arStaffs"] = $staffsList;
		// $arResult["arSenders"] = BitrixRest::call("messageservice.sender.list",array());
		
		// self::eLog($arResult,"AloVoiceConnector::ADMIN ACTION AR RESULT:");
		
		// //return $arResult;
		// //include($this->rootdir."/template/dashboard.php");
	// }
	
	public function setBxOutToken($token){
		if(!empty($token)){
			$this->bxOutToken = $token;
		}
	}
	
	public function getBxOutToken(){
		return $this->bxOutToken;
	}



	// public function bitrixHandle(){
		// if( !empty($_REQUEST) ){
			
			// if(!empty($_REQUEST["loadpage"])){
				// $reqLoadPage = dirname(dirname(dirname(__DIR__)))."/template/".$_REQUEST["loadpage"].".php";
				// if(file_exists($reqLoadPage)){
					// include($reqLoadPage);
				// }
				// return true;
			// }
			
			// if(!empty($_REQUEST["tgmethod"])){
				// $tgl = new \TGA\ATelegram(); 
				
				// $tgla = $tgl->doTgMethod($_REQUEST);
				
				// $js_tgl = json_encode(array("Request"=>$_REQUEST["tgmethod"], "answer"=>$tgla));
				// self::eLog("AloVoice Connector: TG CHECK:".$js_tgl);
				
				// echo $js_tgl;
				
				// return true;
			// }
			
			// if(!empty($_REQUEST["restmethod"])){
				
				// $restAnswer = BitrixRest::doMethod($_REQUEST);
				
				// if(is_string($restAnswer)) {
					// echo $restAnswer;
				// } else {
					// //header("Content-type:application/json");
					// echo json_encode($restAnswer);
				// }
				
				// return true;
			// } 

			// self::eLog($_REQUEST,"bitrixHandle: Begin:BitrixEvents: Event[".$_REQUEST["event"]."] OR PLACEMENT[".$_REQUEST["PLACEMENT"]."]");
			
			
			// if(!empty($_REQUEST["tugsendsms"]) && !empty($_REQUEST["to"]) && !empty($_REQUEST["message"])){
				// return AloVoiceActions::doSendSms(array("sendto"=>$_REQUEST["to"],"message"=>$_REQUEST["message"]));
			// }
			
			// if(!empty($_REQUEST["type"]) && !empty($_REQUEST["code"]) && !empty($_REQUEST["message_id"])){
				// if($_REQUEST["type"]=="SMS" && ($_REQUEST["code"]=="allonote" || $_REQUEST["code"]=="allotg") ){
					// return new BitrixEvents($_REQUEST);
				// }
			// }
			
			// if(!empty($_REQUEST["PLACEMENT"]) || !empty($_REQUEST["notif_sender"]) || !empty($_REQUEST["allotg_sender"])){
				// self::eLog("AloVoice Connector: Start Placement BitrixEvent");
				// return new BitrixEvents($_REQUEST);
			// }
			
			// if( (!empty($_REQUEST["event"])) || (!empty($_REQUEST["tgevent"])) ){
				// self::eLog("AloVoice Connector: Start Event BitrixEvent");
				// //$IsBxEventMethods = method_exists(BitrixEvents,strtolower($_REQUEST["event"]));
				// //self::eLog($IsBxEventMethods,"AloVoice Connector: IsBxEventMethods");
				// //if($IsBxEventMethods){
					// return new BitrixEvents($_REQUEST);
				// //}
				// //}
			// }
		// } 
		
		// self::eLog("bitrixHandle: No Request array");
		// return false;
	// }
	
	public function beginCall($data){
				
		$stRes =  self::statAPI("insert",[
			"KEY" => "4Ad49wD",
			'fields' => [
				"CALLDATE"  => date("Y-m-d"),
				"CHANNEL" => (!empty($data["channel"])) ? $data["channel"] : "",
				"TIME_BEGINCALL" => time(),
				"DIALSTATUS" => 'BEGIN',
				"CALL_DATETIME" => date("Y-m-d H:i:s"),
				"HOUR" => date("H"),
			]
		]);
		
		self::eLog($stRes,"--== beginCall STATAPI RES:");
		
		if(!empty($stRes["result"]) && is_numeric($stRes["result"])){
			return $stRes["result"];
		}
		else {
			return 0;
		}
	}
	
	public function startCall($queryData,$full=[]){
		self::eLog($queryData,"--== startCall QUERY:");
		self::eLog($full,"--== startCall FULL:");
		self::eLog($full["ALV_ECALLID"],"--== startCall ALV_ECALLID:");
		
		$outBxCallId = (!empty($full["AloVoice_Outgoing_OriginateCall"])) ? $full["AloVoice_Outgoing_OriginateCall"] : false;
		if(empty($outBxCallId) && !empty($full["BX24_CALLID"])){
			$outBxCallId = $full["BX24_CALLID"];
		}
		
		if(empty($outBxCallId)){
			$bxRes = BxRest::call("telephony.externalcall.register",$queryData);
			self::eLog($bxRes,"--== startCall RES:");
		} else {
			$bxRes = [
				"result" => [
					"CALL_ID" => $outBxCallId
				]
			];
			if(!empty($full["BX24_CRM_TYPE"])){ $bxRes["result"]["CRM_ENTITY_TYPE"] = $full["BX24_CRM_TYPE"]; }
			if(!empty($full["BX24_CRM_ID"])){ $bxRes["result"]["CRM_ENTITY_ID"] = $full["BX24_CRM_ID"]; }
		}
		$from_number = ($queryData["TYPE"]=="1" && !empty($queryData["PHONE_NUMBER"])) ? $queryData["PHONE_NUMBER"] : false;
		if( empty($from_number) && $queryData["TYPE"]!="1" && !empty($queryData["LINE_NUMBER"])){ $from_number = $queryData["LINE_NUMBER"]; }
		
		$to_number = ($queryData["TYPE"]!="1" && !empty($queryData["PHONE_NUMBER"])) ? $queryData["PHONE_NUMBER"] : false;
		if( empty($to_number) && $queryData["TYPE"]=="1" && !empty($queryData["LINE_NUMBER"])){ $to_number = $queryData["LINE_NUMBER"]; }
		
		$direction = (!empty($full["BX24_DIRECTION"])) ? $full["BX24_DIRECTION"] : false;
		if(empty($direction) && !empty($full["context"]) && $full["context"]=="from-internal"){
			$direction = "OUTCALL";
		}
		if(empty($direction) && !empty($full["__DIRECTION"])){
			$direction = $full["__DIRECTION"];
		}
		
		$innerphone = (!empty($queryData["USER_PHONE_INNER"])) ? $queryData["USER_PHONE_INNER"] : "";
		if(empty($innerphone) && !empty($full["calleridnum"]) && is_numeric($full["calleridnum"])){
			$innerphone = $full["calleridnum"];
		}
		
		$userID = (!empty($queryData["USER_ID"])) ? $queryData["USER_ID"] : "";
		if(empty($userID) && !empty($full["BX24_USERID"])){ $userID = $full["BX24_USERID"]; }
		
		$stRes = self::statAPI("update",[
			'where' => ["ID" => $full["ALV_ECALLID"]],
			"KEY" => "4Ad49wD",
			'fields' => [
				"DIALSTATUS" => 'DIALBEGIN',
				"TIME_DIALBEGIN" => time(),
				"BXCALLID" => (!empty($bxRes["result"]["CALL_ID"])) ? $bxRes["result"]["CALL_ID"] : "",
				"CHANNEL" => (!empty($full["channel"])) ? $full["channel"] : "",
				"USER_ID" => $userID,
				"FROM_NUMBER" => $from_number,
				"TO_NUMBER" => $to_number,
				"LINE_NUMBER" => (!empty($queryData["LINE_NUMBER"])) ? $queryData["LINE_NUMBER"] : "",
				// "QUEUENUM" => "99999",
				"INNER_PHONE" => $innerphone,
				"DIRECTION" => (!empty($direction)) ? $direction : "INBOUND",
			]
		]); 
	
		// $stRes =  self::statAPI("insert",[
			// 'fields' => [
				// "CALLDATE"  => date("Y-m-d"),
				// "BXCALLID" => (!empty($bxRes["CALL_ID"])) ? $bxRes["CALL_ID"] : "",
				// "CHANNEL" => (!empty($full["channel"])) ? $full["channel"] : "",
				// "USER_ID" => (!empty($queryData["USER_ID"])) ? $queryData["USER_ID"] : "",
				// "FROM_NUMBER" => $from_number,
				// "TO_NUMBER" => $to_number,
				// "LINE_NUMBER" => (!empty($queryData["LINE_NUMBER"])) ? $queryData["LINE_NUMBER"] : "",
				// // "QUEUENUM" => "99999",
				// "INNER_PHONE" => (!empty($queryData["USER_PHONE_INNER"])) ? $queryData["USER_PHONE_INNER"] : "",
				// "TIME_BEGINCALL" => time(),
				// "DIALSTATUS" => 'BEGIN',
				// // "TIME_QUEUEJOINTIME" => "",
				// //"TIME_DIALBEGIN" => "1619686154",
				// "DIRECTION" => ($queryData["TYPE"]=="1") ? "INBOUND" : "OUTCALL",
				// "HOUR" => date("H")
			// ]
		// ]);
		
		// self::eLog($stRes,"--== startCall STATAPI RES:");
		
		// if(!empty($stRes["result"]) && is_numeric($stRes["result"])){
			// $bxRes["ECALLID"] = $stRes["result"];
		// }
		
		/*
		{
		 "ID" : "",
		  "CALLDATE" : "",
		  "FULLINFO" : "",
		  "BXCALLID" : "",
		  "CHANNEL" : "",
		  "USER_ID" : "",
		  "FROM_NUMBER" : "",
		  "TO_NUMBER" : "",
		  "LINE_NUMBER" : "",
		  "QUEUENUM" : "",
		  "INNER_PHONE" : "",
		  "ANSWEREDTIME" : "",
		  "TIME_BEGINCALL" : "",
		  "TIME_QUEUEJOINTIME" : "",
		  "TIME_DIALBEGIN" : "",
		  "TIME_HANGUP" : "",
		  "CALL_DATETIME" : "",
		  "DIRECTION" : "",
		  "LAST_POSITION" : "",
		  "DIALSTATUS" : "",
		  "REC" : "",
		  "CALLGROUP" : "",
		  "REASONGROUP" : ""
		}
		*/
		//{"CALL_START_DATE":"2021-08-24 12:34","CRM_CREATE":1,"SHOW":1,"DESC":"SIP\/712037006-000003b9","CRM_ENTITY_TYPE":"LEAD","CRM_ENTITY_ID":"58270","TYPE":1,"LINE_NUMBER":"712037006","USER_PHONE_INNER":"3098","USER_ID":"1712","PHONE_NUMBER":"983633660"}
		return $bxRes;
	}
	
	public function finishCall($queryData,$full=[]){
		self::eLog($queryData,"--== finishCall QUERY:");
		self::eLog($full["ALV_ECALLID"],"--== finishCall ALV_ECALLID:");
		
		$goodSecods = 30;
		$bxRes = BxRest::call("telephony.externalcall.finish",$queryData);
		self::eLog($bxRes,"--== finishCall RES:");
		
		
		if(!empty($full["ALV_ECALLID"])){
			
			$duration = (!empty($bxRes["CALL_DURATION"])) ? $bxRes["CALL_DURATION"] : NULL;
			if(empty($duration) && !empty($full["ANSWEREDTIME"])) { $duration = $full["ANSWEREDTIME"]; }
			
			$dialStatus = (!empty($full["DIALSTATUS"])) ? $full["DIALSTATUS"] : "UNKNOWN";
			
			$lastPosition = 'TALK';
			
			if($dialStatus != "ANSWER"){
				$lastPosition = (!empty($full['QUEUENUM'])) ? $full['QUEUENUM'] : "UNKNOWN";
			
				if(empty($lastPosition)){
					if(substr($full["hangupkeys"]["context"],0,3)=="ivr"){
						$lastPosition = 'IVR';
					}
				}
			}
			
			$stRes = self::statAPI("update",[
				'where' => ["ID" => $full["ALV_ECALLID"]],
				"KEY" => "4Ad49wD",
				'fields' => [
					"FULLINFO" => json_encode($full),
					"QUEUENUM" => (!empty($full["QUEUENUM"])) ? $full["QUEUENUM"] : "",
					"ANSWEREDTIME" => $duration,
					"TIME_QUEUEJOINTIME" => (!empty($full["QUEUEJOINTIME"])) ? $full["QUEUEJOINTIME"] : "",
					"TIME_HANGUP" => time(),
					"LAST_POSITION" => $lastPosition,
					"DIALSTATUS" => $dialStatus,
					"REC" => (!empty($queryData["RECORD_URL"])) ? $queryData["RECORD_URL"] : "",
					"GOOD" => (!empty($duration) && $duration>$goodSecods) ? 1 : NULL
				]
			]);
		}
		
		self::eLog($stRes,"--== finishCall STATAPI RES:");
		
		return $bxRes;
	}
	
	public function attachCall($queryData){
		$bxRes = BxRest::call("telephony.externalCall.attachRecord",$queryData);
		self::eLog($bxRes,"--== attachCall RES:");
		return $bxRes;
	}
	
	public function listen(){
		$beginTime = time();
		$checkTimeout = 1; //seconds
		global $calls;
		$calls = array();
		// $bxonusers = array();
		// $bxOnlineUsers = BxRest::call("user.get",array(
			// 'UF_PHONE_INNER' => '_%',
			// //'IS_ONLINE' => 'Y',
		// )); 
		// if(!empty($bxOnlineUsers["result"])){
			// $bxonusers = array();
			// foreach($bxOnlineUsers["result"] as $bxonUser){
				// $bxonusers[$bxonUser["UF_PHONE_INNER"]] = $bxonUser;
			// }
		// }
		
		$bxonusers = $this->getUsersList(false,true);
		
		$this->_client = new \PAMI\Client\Impl\ClientImpl(array(
			'host' => $this->configs["asterisk_host"],
			'port' => $this->configs["asterisk_port"],
			'username' => $this->configs["asterisk_username"],
			'secret' => $this->configs["asterisk_secret"],
			'connect_timeout' => 100,
			'read_timeout' => 1000
		));
		$this->_client->open();
		
		$listener = new AloVoiceHandle($this->configs,$bxonusers);
		$this->_client->registerEventListener(array($listener, 'handle'));
		//$this->_client->registerEventListener(function ($event) { });

		$this->listenOn = true;

		while($this->listenOn) {
			if($this->listenOn === true){
				
				try {
					$this->_client->process();
					
				} catch (Exception $e) {
					AloVoiceConnector::eLog($e->getMessage(),'Error connection, reconnecting...');
					$this->_client->close();
					$this->_client->open();

				}
				
				$period = time() - $beginTime;
				if($period >= $checkTimeout){
					$beginTime = time();
					$this->runAlovoiceAgents();
				}
				usleep(1000);
			} else {
				$this->_client->close();
			}
		}
		/*
		while($this->listenOn) {
			if($this->listenOn === true){
				$this->_client->process();
				usleep(1000);
			} else {
				$this->_client->close();
			}
		}*/
	}
	
	public function getUsersList($isOnline=false,$byNum=false){
		$resUsers = [];
		$uParams = array( 'UF_PHONE_INNER' => '_%' );
		
		if($isOnline){
			$uParams['IS_ONLINE'] = 'Y';
		}
		
		$bxOnlineUsers = BxRest::call("user.get",$uParams); 
		
		if(!empty($bxOnlineUsers["result"])){
			if(!empty($byNum)){
				$resUsers = array();
				foreach($bxOnlineUsers["result"] as $bxonUser){
					$resUsers[$bxonUser["UF_PHONE_INNER"]] = $bxonUser;
				}
			}
			else {
				$resUsers = $bxOnlineUsers["result"];
			}
		}
		
		// self::eLog($resUsers,"--== bxOnlineUsers ONLINEs on BITRIX");
		
		return $resUsers;
	}
	
	public function processIncomSMS($from, $sms){
		$grID = "$02000000706066180000000000000000";
		
		if(substr($sms,0,5) == 'Rasx:' || substr($sms,0,5) == 'Post:'){
			self::eLog($sms,"--== SMS processIncomSMS:",true);
			$taskLink = AloVoiceRest::alovoice_taskadd($sms);
			self::eLog($taskLink,"--== TASK Add RES:",true);
			
			self::sendTgMsg(["toid"=>$grID, "message"=>$sms]);
		}
		elseif($sms == 'testmsg'){
			self::sendTgMsg(["toid"=>$grID, "message"=>$sms]);
		}
		elseif($sms == 'userslist'){
			$bxOnlineUsers = BxRest::call("user.get",array(
				'UF_PHONE_INNER' => '_%',
				'IS_ONLINE' => 'Y',
			)); 

			// self::eLog($bxOnlineUsers,"--== bxOnlineUsers ONLINEs on BITRIX");
		}
		else {
		
			$crmEntitySearchResult = BxRest::call("telephony.externalCall.searchCrmEntities",array(
				'PHONE_NUMBER' => $from,
			));
			self::eLog($crmEntitySearchResult,"--== SMS searchCrmEntities RESULT:",true);
			
			if(!empty($crmEntitySearchResult["result"])){
				$entTypes = array(
					"LEAD" => 1,
					"DEAL" => 2,
					"CONTACT" => 3,
					"COMPANY" => 4,
					"INVOICE" => 5,
					"Quote" => 7,
					"Requisites" => 8
				);
				if(!empty($crmEntitySearchResult["result"][0])){
					$crmEnt = $crmEntitySearchResult["result"][0];
					if(!empty($crmEnt["CRM_ENTITY_ID"])){
						$crmType = $crmEnt["CRM_ENTITY_TYPE"];
						$crmEntId = $crmEnt["CRM_ENTITY_ID"];
						
						$dateTime = date('Y-m-d').'T'.date('H:i:s').'+05:00';
						
						$addSmsActivity = BxRest::call("crm.activity.add",array(
							'fields' => [
								"OWNER_TYPE_ID" => $entTypes[$crmType],
								"OWNER_ID" => $crmEntId,
								"PROVIDER_ID" => 'REST_APP',
								"PROVIDER_TYPE_ID" => 'alosms',
								"SUBJECT" => "Входящий SMS от: ".$from,
								"COMPLETED" => "Y",
								"RESPONSIBLE_ID" => 1,
								"DESCRIPTION" => $sms
							]
						));	
						
						self::eLog($addSmsActivity,"--== SMS Activity add RES:",true);				
					}
				}
			}
		}
		
		if(!empty($taskLink)) { $sms = $sms."\n Задача: <a href='".$taskLink."'>".$taskLink.'</a>'; }
		$arResievers = array(1,6,8);
		foreach($arResievers as $rcvr ){
			$smsIncomIMMsgResult = BxRest::call("im.notify.system.add",array(
				'USER_ID' => $rcvr,
				'MESSAGE' => "SMS сообщения от: ".$from." \n".$sms,
				'MESSAGE_OUT' => $sms,
			));

			self::eLog($smsIncomIMMsgResult,"--== smsIncomIMMsgResult SMS on BITRIX");
		}
	}
	
	public function sendTgMsg($p){
		$TG = new \TGA\ATelegram();
		return $TG->send_telegram_msg($p);
	}
	
	public function runAlovoiceAgents(){
		$now = time();
		// self::eLog('Agent_run...');
		
		$agents = [
			'agentCheckTgStatus' => 60,
			'agentProcessBxLeads' => 65,
			'checkListenerStatus' => 30,
			'agentsCheckDeletedUsersNumber' => 60,
			// 'billz_catalog_infos_synch' => 12000,
			'process_orders_synch' => 60,
		];
		
		
		foreach($agents as $agent=>$atimeout){
			if( empty($this->alvagents[$agent]) ){
				$this->alvagents[$agent] = time();
			}
			$agentPeriod = $now - $this->alvagents[$agent];
			if($agentPeriod > $atimeout){
				$this->alvagents[$agent] = time();
				$this->$agent();
			}
		}
		
		
		
	}
	
	public function process_orders_synch(){
		self::alovoiceRestCmd([ 'restmethod' => 'process_orders_synch' ]);
	}
	public function billz_catalog_infos_synch(){
		self::alovoiceRestCmd([ 'restmethod' => 'billz_catalog_infos_synch' ]);
	}
	
	public function checkListenerStatus(){
		$statusRes = $this->_client->send(new \PAMI\Message\Action\CoreStatusAction);
		$keys = $statusRes->getkeys();
		// self::eLog($keys["response"],"--== *** ===== *** ==== check STATUS RES:", "handler");
	}
	
	public function agentsCheckDeletedUsersNumber(){
		$bxoffusers = array();
		$uids = array();
		$delnums = array();
		$begin = time();
		$bxOffUsersRes = BxRest::call("user.get",array(
			'UF_PHONE_INNER' => '_%',
			'ACTIVE' => 0,
		)); 
		if(!empty($bxOffUsersRes["result"])){
			foreach($bxOffUsersRes["result"] as $bxoffUsr){
				$bxoffusers[$bxoffUsr["UF_PHONE_INNER"]] = $bxoffUsr["ID"];
				$delnums[] = $bxoffUsr["UF_PHONE_INNER"];
				$uids[] = $bxoffUsr["ID"];
			}
		}
		
		return $bxoffusers;
		
		if(!empty($delnums)){

			self::alovoiceRestCmd( array(
				'cmd' => 'delMemeberFromQueues',
				'members' => $delnums,
			));
		}
		
		if(!empty($uids)){
			foreach( $uids as $uid){
				BxRest::call("user.update",array(
					"ID" => $uid, "UF_PHONE_INNER" => '',
				)); 
			}
		}
		
		return ['res'=>[$begin,time()]];
	}
	
	public function alovoiceRestCmd($p){
		
		
		if(empty($p)){ return false; }

		// self::eLog($p,"--== AlvREST PARAMS:");
		
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, 'https://127.0.0.1/bx24/');
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		// curl_setopt($ch, CURLOPT_REFERER, 'https://my2.soliq.uz');
		curl_setopt($ch, CURLOPT_USERAGENT, 'AloVoice-2.0.0.1');
		curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
		curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
		curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
		// curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
		curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($p) );
		
		$body = curl_exec($ch);
		// self::eLog($body,"--== AlvREST RES:");
		
		if($body === false){
			$errors = curl_error($ch);
		}

		curl_close($ch);
		
		
		return (!empty($errors)) ? $errors : $body;
	}
	
	public function agentCheckTgStatus(){
		// self::eLog(time(),'Agent TG Check[agentCheckTgStatus]: ');
		// $TG = new \TGA\ATelegram();
		// $TG->checkTG();
		// $TG = null;
		// unset($TG);
	}
	
	public function agentProcessBxLeads(){
		self::eLog(time(),'Begin Leads Process[agentProcessBxLeads]:...');
		$leadsLoadResult = BxRest::call("crm.lead.list",array(
			'filter' => ['HAS_PHONE'=>'Y', 'HAS_IMOL'=> 'N', '!UTM_CONTENT' => 'DONE'],
			'select' => [ 'ID','TITLE','HAS_PHONE','HAS_IMOL','PHONE','IM','CONTACT_ID','UTM_CONTENT' ],
		));
		
		if(!empty($leadsLoadResult["result"][0])){
			$arLead = $leadsLoadResult["result"][0];
			
			self::eLog($arLead,"--== leadsLoadResult LEADs from BX");
			
			BxRest::call("crm.lead.update",array(
				'id' => $arLead['ID'],
				// 'fields' => [ 'UF_CRM_ALV_TG_CHECKER'=>'DONE' ],
				'fields' => [ 'UTM_CONTENT'=>'DONE' ],
			));
								
			if(!empty($arLead['CONTACT_ID'])){
				$leadContactLoadRes = BxRest::call("crm.contact.get",array(
					'id' => $arLead['CONTACT_ID']
				));
				$arIM = (!empty($leadContactLoadRes["result"]['IM'])) ? $leadContactLoadRes["result"]['IM'] : false;
				self::eLog($arIM,"--== leadsLoadResult CONTACT Loeaded RES:");
				if($leadContactLoadRes["result"]["HAS_IMOL"]){
					if(!empty($leadContactLoadRes["result"]["IM"])){
						foreach($leadContactLoadRes["result"]["IM"] as $ims){
							if($ims["VALUE_TYPE"]=="IMOL"){
								
								BxRest::call("crm.lead.update",array(
									'id' => $arLead['ID'],
									'fields' => [ 'IM'=>[['VALUE'=>$ims["VALUE"],'VALUE_TYPE'=>'IMOL']] ],
								));
								
								return true;
							}
						}
					}
				}
			}
			
			if(!empty($arLead['COMPANY_ID'])){
				$leadCompanyLoadRes = BxRest::call("crm.company.get",array(
					'id' => $arLead['COMPANY_ID']
				));
				self::eLog($leadCompanyLoadRes["result"]['IM'],"--== leadsLoadResult COMPANY Loeaded RES:");
				if($leadCompanyLoadRes["result"]["HAS_IMOL"]){
					if(!empty($leadCompanyLoadRes["result"]["IM"])){
						foreach($leadCompanyLoadRes["result"]["IM"] as $ims){
							if($ims["VALUE_TYPE"]=="IMOL"){
								
								BxRest::call("crm.lead.update",array(
									'id' => $arLead['ID'],
									'fields' => [ 'IM'=>[['VALUE'=>$ims["VALUE"],'VALUE_TYPE'=>'IMOL']] ],
								));
								
								return true;
							}
						}
					}
				}
			}
			
			// self::checkTgContact($arLead);
		}

	}
	
	public function getWavAudio($file){
		$file = preg_replace("/\s/","+",$file);
		
		if(!file_exists($file)){
			echo 'File Audio: ['.$file.'] not found!';
			return false;
		}
		
		$fileSize = filesize($file);
		if($fileSize>100){
			$arFname = explode("/",$file);
			$fname = end($arFname);
			$fname = substr($fname,0,-4);
			$saveFile = __DIR__.'/'.$fname.'.mp3';

			$execCmd = '/usr/bin/lame -b 16 '.$file.' '.$saveFile;
			exec($execCmd , $output, $convertres);
			unlink($file);

			if($convertres==0 || $convertres=="0" ){
				header("Content-Transfer-Encoding: binary");
				header("Content-Type: audio/mpeg");
				header('Content-length: ' . filesize($saveFile)); 
				header('Content-Disposition: inline');
				//Otherwise you can add it like so, in order to give the download a filename
				header('Content-Disposition: inline;filename='.$fname.'.mp3');
				header('Cache-Control: no-cache');


				readfile($saveFile);
				exit;
	
				die();
			} 
		} 
		
		return false;
	}
	
	public function audio_to_http($file,$newfile){
		if(!file_exists($file)){
			self::eLog('File Audio: ['.$file.'] not found!');
			return false;
		}
		$fileSize = filesize($file);
		if($fileSize>100){
			$arConfs = self::getConfigs();
			$saveFile = dirname(dirname(dirname(__DIR__))).'/'.$arConfs["files_folder"].$newfile;
			$retFile = $arConfs["alovoice_host"].$arConfs["files_folder"].$newfile;
			$execCmd = '/usr/bin/lame -b 16 '.$file.' '.$saveFile;
			exec($execCmd , $output, $convertres);
			AloVoiceConnector::eLog($execCmd ,'LAME execCmd ... ');
			AloVoiceConnector::eLog($convertres,'LAME convertres... ');
			AloVoiceConnector::eLog($output,'LAME output... ');
			AloVoiceConnector::eLog('saveFile:['.$saveFile.']');
			AloVoiceConnector::eLog('retFile:['.$retFile.']');
			AloVoiceConnector::eLog('filesize:['.$fileSize.']');
			// unlink($file);
			AloVoiceConnector::eLog('removed?:['.file_exists($file).']');
			if($convertres==0 || $convertres=="0" ){
				return $retFile;
			} else {
				return false;
			}
		} else {
			return false;
		}
	}
	
	public function listenStop(){
		$this->listenOn = false;
	}
	
	// public function doAuth(){
		// $this->_error = "";
		// if(!empty($_REQUEST["auth"]["access_token"])){
			// return true;
		// }
		// $this->eLog($_SESSION, "========== doAuth: Session:");
		
		// //test
		// //echo 'Test text123';
		// return true;
		
		// // clear auth session
		// if( (isset($_REQUEST["clear"]) && $_SERVER["REQUEST_METHOD"] == "POST")) // || (1==1)
		// {
			// unset($_SESSION["query_data"]);
		// }
		// elseif( !empty($_REQUEST["tgevent"]) ) {
			// return true;
		// }
		// elseif( empty($_SESSION["query_data"]) || ( $_SESSION["query_data"]["expires"]<time() ) ) {
			// if(isset($_REQUEST["code"])){
				// $code = $_REQUEST["code"];
				// $domain = $_REQUEST["domain"];
				// $member_id = $_REQUEST["member_id"];

				// $params = array(
					// "grant_type" => "authorization_code",
					// "client_id" => $this->configs["bx_client_id"],
					// "client_secret" => $this->configs["bx_client_secret"],
					// "redirect_uri" => $this->configs["asterisk_host"],
					// "scope" => "app,crm,log,user",
					// "code" => $code,
				// );
				// $path = "/oauth/token/";

				// $this->eLog("Code confirmation authorizing...");
				// $this->eLog($_SESSION["orig_request"],"Original Request begin: ");
				// $query_data =  BitrixRest::query("GET", $this->configs["bitrix_domain_protocol"]."://".$domain.$path, $params);

				// if(isset($query_data["access_token"]))
				// {
					// $_SESSION["query_data"] = $query_data;
					// $_SESSION["query_data"]["ts"] = time();
					
					// $req_is_admin = BitrixRest::call("user.admin");
					// $_SESSION["is_admin"] = ($req_is_admin["result"]=="1") ? true : false;
					
					// $req_arUser = BitrixRest::call("user.current");
					// $_SESSION["aruser"] =  $req_arUser["result"];
					
					// $origRequest = $_SESSION["orig_request"];
					// unset($_SESSION["orig_request"]);
					// $this->redirect($this->configs["asterisk_host"]."?".http_build_query($origRequest));
				// }
				// else
				// {
					// $error = "Произошла ошибка авторизации! ".print_r($query_data, 1);
				// }
			// } else {
				// $_SESSION["orig_request"] = $_REQUEST;
				// //$domain = $_POST["portal"];
				// $params = array(
					// "response_type" => "code",
					// "client_id" => $this->configs["bx_client_id"],
					// "redirect_uri" => $this->configs["asterisk_host"],
				// );
				// $authUrl = $this->configs["bitrix_domain_protocol"]."://".$this->configs["bitrix_domain"]."/oauth/authorize/";
				// $this->eLog($authUrl,"___auth_query_ URL");
				// $this->eLog($params,"___auth_query_ PARAMS");

				// $this->redirect($authUrl."?".http_build_query($params));
				// //$this->redirect($this->configs["bitrix_domain_protocol"]."://".$this->configs["bitrix_domain"].$path."?".http_build_query($params));
			// }
			// /*
		 // SESSION VARS after auth..........
		  // ["query_data"] => array(12) {
			// ["access_token"] => string(70) "f0ddb15d0041355e004080f000000006201c03054eac11dd00c44721c9b1c0f07ffb73"
			// ["expires"] => int(1571937776)
			// ["expires_in"] => int(3600)
			// ["scope"] => string(16) "app,crm,log,user"
			// ["domain"] => string(15) "4uz.bitrix24.ru"
			// ["server_endpoint"] => string(31) "https://oauth.bitrix.info/rest/"
			// ["status"] => string(1) "L"
			// ["client_endpoint"] => string(29) "https://4uz.bitrix24.ru/rest/"
			// ["member_id"] => string(32) "cbb436f0f1d7471ce732a524cb8aeb17"
			// ["user_id"] => int(6)
			// ["refresh_token"] => string(70) "e05cd95d0041355e004080f000000006201c03b6d93abda1827cf8360941e73849c3c2"
			// ["ts"] => int(1571934176)
		  // }
		  // ["is_admin"] => bool(false)
		  // ["aruser"] => array(36) {
			// ["ID"] => string(1) "6"
			// ["ACTIVE"] => string(1) "1"
			// ["EMAIL"] => string(23) "knavruzov@technounit.uz"
			// ["NAME"] => string(12) "КУЛДАШ"
			// ["LAST_NAME"] => string(16) "НАВРУЗОВ"
			// ["SECOND_NAME"] => string(20) "Шухратович"
			// ["PERSONAL_GENDER"] => string(1) "M"
			// ["PERSONAL_PROFESSION"] => string(0) ""
			// ["PERSONAL_WWW"] => string(0) ""
			// ["PERSONAL_BIRTHDAY"] => string(25) "1983-09-09T03:00:00+04:00"
			// ["PERSONAL_PHOTO"] => string(90) "https://cdn.bitrix24.ru/b11827782/main/11e/11e1010b3a10f6dfe0c657bb9ddabdee/ava_kulya2.jpg"
			// ["PERSONAL_ICQ"] => string(0) ""
			// ["PERSONAL_PHONE"] => string(0) ""
			// ["PERSONAL_FAX"] => string(0) ""
			// ["PERSONAL_MOBILE"] => string(13) "+998977076909"
			// ["PERSONAL_PAGER"] => string(0) ""
			// ["PERSONAL_STREET"] => string(0) ""
			// ["PERSONAL_CITY"] => string(0) ""
			// ["PERSONAL_STATE"] => string(0) ""
			// ["PERSONAL_ZIP"] => string(0) ""
			// ["PERSONAL_COUNTRY"] => string(0) ""
			// ["WORK_COMPANY"] => string(0) ""
			// ["WORK_POSITION"] => string(22) "Программист"
			// ["WORK_PHONE"] => string(0) ""
			// ["UF_DEPARTMENT"] => array(1) { [0] =>   string(2) "10" }
			// ["UF_INTERESTS"] => string(0) ""
			// ["UF_SKILLS"] => string(0) ""
			// ["UF_WEB_SITES"] => string(0) ""
			// ["UF_XING"] => string(0) ""
			// ["UF_LINKEDIN"] => string(0) ""
			// ["UF_FACEBOOK"] => string(0) ""
			// ["UF_TWITTER"] => string(0) ""
			// ["UF_SKYPE"] => string(0) ""
			// ["UF_DISTRICT"] => string(0) ""
			// ["UF_PHONE_INNER"] => string(4) "1002"
			// ["USER_TYPE"] => string(0) ""
		  // }
			// }
		
			// */
		// } 
	// }


	public function innTaxFields($fiz=false){
		if($fiz){
			return ["tin", "ns10Code", "ns10Name", "ns11Code", "ns11Name", "name", "nameFull", "address", "regNum", "regDate", "fund", "gdFullName", "gdTin", "gdTelWork", "gdTelHome", "gbFullName", "gbTin", "gbTelWork", "gbTelHome", "nc1Code", "nc1Name", "nc2Code", "nc2Name", "nc3Code", "nc3Name", "nc4Code", "nc4Name", "nc5Code", "nc5Name", "nc6Code", "nc6Name", "ns1Code", "ns1Name", "ns2Code", "ns2Name", "ns3Code", "ns3Name", "ns4Code", "ns4Name", "ns13Code", "ns13Name", "na1Code", "na1Name", "account", "dateTin", "stateCode", "stateName"];
		}
		return [
			"tax_tin" => 'ИНН', 
			"tax_ns10Code" => 'Код города', 
			"tax_ns10Name" => 'Город', 
			"tax_ns11Code" => 'Код района', 
			"tax_ns11Name" => 'Район', 
			"tax_name" => 'Наименование', 
			"tax_nameFull" => 'Наименование подробно', 
			"tax_address" => 'Адрес', 
			"tax_regNum" => 'Номер регистрации', 
			"tax_regDate" => 'Дата регистрации', 
			"tax_fund" => 'Уставной фонд', 
			"tax_gdFullName" => 'ФИО Руководителя', 
			"tax_gdTin" => 'ИНН Руководителя', 
			"tax_gdTelWork" => 'Телефон Руководителя', 
			"tax_gdTelHome" => 'Телефон дом. Руководителя', 
			"tax_gbFullName" => 'ФИО Бухгалтера', 
			"tax_gbTin" => 'ИНН Бухгалтера', 
			"tax_gbTelWork" => 'Телефон Бухгалтера', 
			"tax_gbTelHome" => 'Телефон дом. Бухгалтера', 
			"tax_nc1Code" => 'Код СООГУ', 
			"tax_nc1Name" => 'СООГУ описание', 
			"tax_nc2Code" => 'Код ОКОНХ', 
			"tax_nc2Name" => 'Вид деятельности по ОКОНХ', 
			"tax_nc3Code" => 'Код собственности', 
			"tax_nc3Name" => 'Тип собственности', 
			"tax_nc4Code" => 'Код ОПФ', 
			"tax_nc4Name" => 'ОПФ описание', 
			"tax_nc5Code" => 'Код района регистрации', 
			"tax_nc5Name" => 'Район регистрации', 
			"tax_nc6Code" => 'Код ОКЭД', 
			"tax_nc6Name" => 'ОКЭД описание', 
			"tax_ns1Code" => 'Код деятельности', 
			"tax_ns1Name" => 'Направление деятельности', 
			"tax_ns2Code" => 'МФО', 
			"tax_ns2Name" => 'Банк', 
			"tax_ns3Code" => 'Код СООГУ', 
			"tax_ns3Name" => 'СООГУ описание', 
			"tax_ns4Code" => 'Код собственности', 
			"tax_ns4Name" => 'Форма собственности', 
			"tax_ns13Code" => 'Код Налогового объязательства', 
			"tax_ns13Name" => 'Налоговое объязательства', 
			"tax_na1Code" => 'Код ОПФ сокр.', 
			"tax_na1Name" => 'ОПФ сокр. описание', 
			"tax_account" => 'Р/с', 
			"tax_dateTin" => 'Дата и время регистрации ИНН', 
			"tax_stateCode" => 'Статус код', 
			"tax_stateName" => 'Статус'
		];
		//return ["tin", "ns10Code", "ns10Name", "ns11Code", "ns11Name", "name", "nameFull", "address", "regNum", "regDate", "fund", "gdFullName", "gdTin", "gdTelWork", "gdTelHome", "gbFullName", "gbTin", "gbTelWork", "gbTelHome", "nc1Code", "nc1Name", "nc2Code", "nc2Name", "nc3Code", "nc3Name", "nc4Code", "nc4Name", "nc5Code", "nc5Name", "nc6Code", "nc6Name", "ns1Code", "ns1Name", "ns2Code", "ns2Name", "ns3Code", "ns3Name", "ns4Code", "ns4Name", "ns13Code", "ns13Name", "na1Code", "na1Name", "account", "dateTin", "stateCode", "stateName"];
	}
	
	public function innFields($fiz=false){
		if($fiz){
			return ["ns10Code","ns11Code","shortName","tin","name","statusCode","statusName","mfo","account","address","oked","directorTin","director","accountant","isBudget","isItd","personalNum","fullName","passSeries","passNumber","passOrg","passIssueDate","districtId","regionId","passport","bankAccount","bankCode","shortname","regCode","VATRegCode","company"];
		}
		return ["ns10Code","ns11Code","shortName","tin","name","statusCode","statusName","mfo","account","address","oked","directorTin","director","accountant","isBudget","regCode","VATRegCode","passport","passOrg","passIssueDate","districtId","regionId","company","bankAccount","bankCode","shortname","fullname"];
	}
	
	// public function innFields(){
		// $arInfo = self::innrequest("303903621");
		// $arInfo = self::innrequest("303903621");
		// $innResFields = [];
		// if(!empty($resINN)){
			// foreach($resINN as $k=>$v){
				// $innResFields[] = $k;
			// }
			// $innResTxt = $resINN["fullname"].", ".$resINN["director"].", ".$resINN["address"].", ".$resINN["account"];
		// }
	// }
	
	public function didox_inn($inn=false){
		$frominn = '303903621';
		$didoxTokenFile = __DIR__.'/didox.json';
		$didoxToken = false;
		$jsDidoxToken = file_get_contents($didoxTokenFile);
		$timerz = 36000;
		if(!empty($jsDidoxToken)){
			$arDdxToken = json_decode($jsDidoxToken,true);
			if(!empty($arDdxToken["time"]) && !empty($arDdxToken["token"])){
				$ddxrz = time()-$arDdxToken["time"];
				if($ddxrz<$timerz){
					$didoxToken = $arDdxToken["token"];
				}
			}
		}
		
		if(empty($didoxToken)){
			$ddxRes = self::didoxrequest(false,"user/".$frominn."/token",["password"=>"mteamgfhjkm"]);
			if(!empty($ddxRes) && strlen($ddxRes)>20){
				if(file_put_contents($didoxTokenFile,json_encode(["time"=>time(),"token"=>$ddxRes]))){
					$didoxToken = $ddxRes;
				}
			}
			// return $ddxRes;
		}
		
		if(!empty($didoxToken) && !empty($inn)){
			$ddxInnRes = self::didoxrequest($didoxToken,"info/".$inn);
			
			$arInnRes = json_decode($ddxInnRes,true);
			if(!empty($arInnRes)){
				return $arInnRes;
			}
		}
		
		return false;
	}
	
	public function didoxrequest($t,$m,$d=false){
		if(empty($m)){ return ""; }
				  //https://api.goodsign.biz/waltz/goodsign/0.0.1/user/303903621/token
		$urlrest = 'https://api.goodsign.biz/waltz/goodsign/0.0.1/'.$m;
		// $urlrest = 'https://api.goodsign.biz/waltz/goodsign/0.0.1/info/'.$inn;
		$curl = curl_init();
		
		$curlParams = array(
			CURLOPT_URL => $urlrest,
			CURLOPT_RETURNTRANSFER => true,
			CURLOPT_ENCODING => "",
			CURLOPT_MAXREDIRS => 10,
			CURLOPT_TIMEOUT => 0,
			CURLOPT_FOLLOWLOCATION => true,
			CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
			CURLOPT_CUSTOMREQUEST => "GET",
			//CURLOPT_HTTPHEADER => array( "Authorization: Basic 37de0156ce4a44e0f33e7ead8d65a4d5c10e3192" ),
			CURLOPT_HTTPHEADER => array( 
				"Accept: application/json", 
				"Origin: https://didox.uz", 
				"Referer: https://didox.uz/",
				"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36" 
			),
		);
		
		if(!empty($t)){
			$curlParams[CURLOPT_HTTPHEADER][] = "user-key: ".$t;
		}
		
		if(!empty($d)){
			$curlParams[CURLOPT_CUSTOMREQUEST] = "POST";
			$curlParams[CURLOPT_POSTFIELDS] = $d;
			// curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
		}
			
		curl_setopt_array($curl,$curlParams);
		$response = curl_exec($curl);

		$info = curl_getinfo($curl);
		curl_close($curl);

		return $response;
		// return json_decode($response,true);
	}
	
	public function nn($number,$nplus=false) {
		// self::eLog($number,"Number test 1");
		$number = preg_replace("/[^0-9]/", '', $number);
		// self::eLog($number,"Number test 2");
		if(empty($number)){ return false; }
		// self::eLog($number,"Number test 3");
		if(strlen($number)==9){
			$number = '+998'.$number;
		} elseif((strlen($number)==11) && (substr($number,0,1)=="7")){
			$number = '+'.$number;
		} elseif( (strlen($number)==12) && (substr($number,0,3)=="998" )){
			$number = '+'.$number;
		}
		// self::eLog($number,"Number test 4");
		return ($nplus) ? substr($number,1) : $number;
	}
	
	public function statAPI($m,$p){
		
		if(empty($m)){ return false; }
		
		$params = [ "method" => $m ];
		if(!empty($p)){
			$params["params"] = $p;
		}
		
		self::eLog($params,"--== statAPI PARAMS:");
		
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, 'https://edo.4u.uz/agentst/');
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		// curl_setopt($ch, CURLOPT_REFERER, 'https://my2.soliq.uz');
		curl_setopt($ch, CURLOPT_USERAGENT, 'AloVoice-2.0.0.1');
		curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
		curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
		curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
		curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
		curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params) );
		
		$body = curl_exec($ch);
		
		curl_close($ch);
		return json_decode($body,true);
	}
	
	public function requesTaxInn($inn){
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, 'https://my2.soliq.uz/main/info/personal/data?tin='.$inn);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_REFERER, 'https://my2.soliq.uz');
		curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1');
		
		$body = curl_exec($ch);
		
		curl_close($ch);
		$arResults = json_decode($body,true);
		return (!empty($arResults["data"])) ? $arResults["data"] : [];
	}
	
	public function ralv($m,$p=[]){
		
		if(empty($m)){ return false; }
		
		$p["restmethod"] = $m ;
		
		//http://192.168.123.6/bx24/?restmethod=alovoice_dongle_channels
		self::eLog($p,"--== rAlv PARAMS:");
		
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, 'http://192.168.123.6/bx24/');
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_USERAGENT, 'AloVoice-2.0.1.1');
		curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
		curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
		curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
		// curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
		if(!empty($p)){
			curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($p) );
		}
		
		$body = curl_exec($ch);
		
		curl_close($ch);
		return json_decode($body,true);
	}
	
	public function redirect($url){
		Header("HTTP 302 Found");
		Header("Location: ".$url);
		die();
	}
	
	public function pdu_decode($t){
		return AloPdu::pdu_decode($t);
	}
	
	public function getSmsLog($id){
		if(empty($id)){
			return false;
		}
		if(!file_exists(dirname(dirname(dirname(__DIR__)))."/files/smss/".$id)){
			return false;
		}
		$jsData = file_get_contents(dirname(dirname(dirname(__DIR__)))."/files/smss/".$id);
		
		return json_decode($jsData,1);
	}
	public function saveSmsLog($data){
		if(empty($data["message_id"])){
			return false;
		}
		file_put_contents(dirname(dirname(dirname(__DIR__)))."/files/smss/".$data["message_id"], json_encode($data));
	}
	
	public function eLog($data, $title = '', $lfile=''){
	
		if(is_object($data)){
			$data = (array)$data;
		}
		
		$logdatafilename = date("Ymd");
		
		$log = "\n------------------------\n";
		$log .= date("Y.m.d G:i:s")." *** ";
		
		if(!empty($title)) { $log .= $title."\n"; }
		
		$log .= (is_array($data)) ?  json_encode($data) : $data; //, JSON_PRETTY_PRINT
		
		$logfile = ( (!empty($lfile)) && (!is_bool($lfile)) ) ? dirname(dirname(dirname(__DIR__)))."/logs/".$lfile."_".$logdatafilename.".log" : dirname(dirname(dirname(__DIR__)))."/logs/events_".$logdatafilename.".log";
		
		file_put_contents($logfile, $log, FILE_APPEND);
		
	}
}