<?php

require_once('URCUDMLData.php');
require_once('ErrorDebug.php');
require_once('URCValues.php');

class URCBtnData {

	var $roomId = -1;
	var $deviceId = -1;

	function __construct($roomId, $deviceId) {		
		$this->roomId = $roomId;
		$this->deviceId = $deviceId;
	}

	public function createBtn($text, $auto_wait, $popup, $activity, $macro) {
		
		$urcPage = new URCPageData($this->roomId, $this->deviceId);
		$pageId = -1;
		$pageBtnIdx = -1;
		if(!$urcPage->getPossibleToAdd($pageId, $pageBtnIdx))
			return false;

		$new_btn_id = -1;
		
		$jsonActivity = json_encode($activity);
		$jsonMacro = json_encode($macro);

		try
		{
			DB::begintransaction();

			$new_btn_id = $this->getNewBtnId();
			$this->setNewBtnId($new_btn_id+1);
			
			//newDevicedBtn is used instead of newBtn because of using as macro.
			$this->newDeviceBtn($new_btn_id, -1, 
				$pageId, $pageBtnIdx, 
				$auto_wait, URCValues::ETYPE_MACRO, $popup,
				'', $text, 0, $jsonActivity, $jsonMacro);			
			DB::commit();
		}
		catch(\Exception $e) 
		{
			DB::rollback();
			return false;
		}

		return array('page_id' => $pageId, 'page_btn_idx' => $pageBtnIdx, 'id' => $new_btn_id);
	}

	public function getMacroFromDevice($conDeviceId) {

		$btn = DB::table('a_btns')->where('link_id', '=', $conDeviceId)
			->where('device_id', '=', $this->deviceId)
			->where('room_id', '=', $this->roomId)->first(); 

		if(!$btn) {
			return false;
		}

		$activity = json_decode($btn->activity);
		$macro = json_decode($btn->macro);

		return array('auto_wait' => $btn->auto_wait, 'edit_type' => $btn->edit_type, 'popup' => $btn->popup,
			'activity' => $activity, 'macro' => $macro);
	}

	public function delMacroFromDevice($conDeviceId) {

		$btn = DB::table('a_btns')->where('link_id', '=', $conDeviceId)
			->where('device_id', '=', $this->deviceId)
			->where('room_id', '=', $this->roomId)->first(); 

		if(!$btn) {
			return false;
		}

		$updatedRow = DB::table('a_btns')->where('link_id', '=', $conDeviceId)
			->where('device_id', '=', $this->deviceId)
			->where('room_id', '=', $this->roomId)->update(array('auto_wait' => 1, 'edit_type' => URCValues::ETYPE_MACRO, 'popup' => 0, 'activity' => '', 'macro' => '')); 

		return true;
	}

	public function storeMacroFromDevice($conDeviceId, $auto_wait, $editType, $popup, $activity, $macro) {
		
		$jsonActivity = json_encode($activity);

		if($editType == URCValues::ETYPE_ACTIVITY) {
			
			/*
			$macro_new = array();
			
			//convert to action
			$arActivity = json_decode($jsonActivity);
			foreach($arActivity as $activity) {
				
				$activity->type = URCValues::ACT_DB;
				//$activity->device_id;
				//$activity->func;
				//$activity->repeate_min = ;
				//$activity->repeate_macro = ;

				$macro_new[] = $activity;
			}

			//add jump
			$macro_new[] = URCBtnData::newJumpAction(URCValues::JUMP_DEVICE, $conDeviceId);
			
			$jsonMacro = json_encode($macro_new);
			*/

			//ErrorDebug::write('jsonActivity:'.$jsonActivity);
			//ErrorDebug::write('jsonMacro:'.$jsonMacro);

			$updatedRow = DB::table('a_btns')->where('link_id', '=', $conDeviceId)
				->where('device_id', '=', $this->deviceId)
				->where('room_id', '=', $this->roomId)->update(array('auto_wait' => $auto_wait, 'edit_type' => $editType, 'popup' => $popup, 'activity' => $jsonActivity, 'macro' => ''));//$jsonMacro)); 

			return true;
		}
		
		if($editType == URCValues::ETYPE_MACRO){
		
			$jsonMacro = json_encode($macro);

			$updatedRow = DB::table('a_btns')->where('link_id', '=', $conDeviceId)
				->where('device_id', '=', $this->deviceId)
				->where('room_id', '=', $this->roomId)->update(array('auto_wait' => $auto_wait, 'edit_type' => $editType, 'popup' => $popup, 'activity' => $jsonActivity, 'macro' => $jsonMacro)); 

			return true;
		}
		
		return false;
	}

	public function getMacro($btnId) {

		$btn = DB::table('a_btns')->where('id', '=', $btnId)
			->where('device_id', '=', $this->deviceId)
			->where('room_id', '=', $this->roomId)->first(); 

		if(!$btn) {
			return false;
		}

		$activity = json_decode($btn->activity);
		$macro = json_decode($btn->macro);

		return array('auto_wait' => $btn->auto_wait, 'edit_type' => $btn->edit_type, 'popup' => $btn->popup,
			'activity' => $activity, 'macro' => $macro);
	}

	public function delMacro($btnId) {

		$btn = DB::table('a_btns')->where('id', '=', $btnId)
			->where('device_id', '=', $this->deviceId)
			->where('room_id', '=', $this->roomId)->first(); 

		if(!$btn) {
			return 0;
		}

		if($btn->link_id >= 0) {
			$updatedRow = DB::table('a_btns')->where('id', '=', $btnId)
				->where('device_id', '=', $this->deviceId)
				->where('room_id', '=', $this->roomId)->update(array('auto_wait' => 1, 'edit_type' => URCValues::ETYPE_MACRO, 'popup' => 0, 'activity' => '', 'macro' => '')); 

			return 1;
		}
		else {

			try
			{
				DB::begintransaction();

				DB::table('a_btns')->where('id', '=', $btnId)
					->where('device_id', '=', $this->deviceId)
					->where('room_id', '=', $this->roomId)->delete();

				$this->sortPageData($btn->page_id, $btn->page_btn_idx);
				
				DB::commit();
			}
			catch(\Exception $e) 
			{
				DB::rollback();
				return 0;
			}

			return 2;
		}
	}

	public function sortPageData($startPageId, $startBtnIdx) {
		
		//$time_start = microtime(true);

		/*
		//slow way

		$btns = DB::table('a_btns')->where('device_id', '=', $this->deviceId)
			->where('room_id', '=', $this->roomId)->where('page_id', '>=', $startPageId)
			->where('page_btn_idx', '>=', 0)->get();

		foreach($btns as $btn) {

			if($btn->page_id == $startPageId) {
				if($btn->page_btn_idx < $startBtnIdx)
					continue;
				$btn->page_btn_idx = $btn->page_btn_idx - 1;

				DB::table('a_btns')->where('id', '=', $btn->id)
					->where('device_id', '=', $btn->device_id)
					->where('room_id', '=', $btn->room_id)->update(array('page_btn_idx' => $btn->page_btn_idx)); 
			}
			else {				
				if($btn->page_btn_idx <= 0) {
					$btn->page_id = $btn->page_id - 1;
					DB::table('a_btns')->where('id', '=', $btn->id)
						->where('device_id', '=', $btn->device_id)
						->where('room_id', '=', $btn->room_id)->update(array('page_id' => $btn->page_id, 'page_btn_idx' => 5)); 
				}
				else {
					$btn->page_btn_idx = $btn->page_btn_idx - 1;

					DB::table('a_btns')->where('id', '=', $btn->id)
						->where('device_id', '=', $btn->device_id)
						->where('room_id', '=', $btn->room_id)->update(array('page_btn_idx' => $btn->page_btn_idx)); 
				}
			}
		}
		*/

		//faster way

		///for current page

		//btn shift
		DB::statement(
			DB::raw(
				"UPDATE a_btns SET page_btn_idx = page_btn_idx -1 WHERE device_id = ? AND room_id = ?
				AND page_id = ? AND page_btn_idx > ?"
			), 

			array($this->deviceId, $this->roomId, $startPageId, $startBtnIdx)
		);
		
		///for next page

		//btn Idx for 0(set page_btn_idx -> -10)
		DB::statement(
			DB::raw(
				"UPDATE a_btns SET page_id = page_id -1, page_btn_idx = -10 WHERE device_id = ? AND room_id = ?
				AND page_id > ? AND page_btn_idx = ?"
			), 
			array($this->deviceId, $this->roomId, $startPageId, 0)
		);		

		//btn Idx from 1-5
		DB::statement(
			DB::raw(
				"UPDATE a_btns SET page_btn_idx = page_btn_idx -1 WHERE device_id = ? AND room_id = ?
				AND page_id > ? AND page_btn_idx <> ?"
			), 

			array($this->deviceId, $this->roomId, $startPageId, -10)
		);

		//recover for page_btn_idx -> -10
		DB::table('a_btns')->where('device_id', '=', $this->deviceId)
			->where('room_id', '=', $this->roomId)->where('page_btn_idx', '=', -10)->update(array('page_btn_idx' => 5));
		
		/*
		$time_end = microtime(true);

		$execution_time = ($time_end - $time_start);
		ErrorDebug::write('workingTime'.$execution_time);
		*/
	}

	public function storeMacro($btnId, $auto_wait, $popup, $activity, $macro) {
		
		$jsonActivity = json_encode($activity);
		$jsonMacro = json_encode($macro);
		
		$updatedRow = DB::table('a_btns')->where('id', '=', $btnId)
			->where('device_id', '=', $this->deviceId)
			->where('room_id', '=', $this->roomId)->update(array('auto_wait' => $auto_wait, 'edit_type' => URCValues::ETYPE_MACRO, 'popup' => $popup, 'activity' => $jsonActivity, 'macro' => $jsonMacro)); 

		return true;
	}
	
	public function getPowerMacro() {

		$btn = DB::table('a_btns')->where('device_id', '=', -1)
			->where('room_id', '=', $this->roomId)->first(); 

		if(!$btn) {
			return false;
		}

		$activity = json_decode($btn->activity);
		$macro = json_decode($btn->macro);

		return array('auto_wait' => $btn->auto_wait, 'edit_type' => $btn->edit_type, 'popup' => $btn->popup,
			'activity' => $activity, 'macro' => $macro);
	}

	public function delPowerMacro() {

		$btn = DB::table('a_btns')->where('device_id', '=', -1)
			->where('room_id', '=', $this->roomId)->first(); 

		if(!$btn) {
			return false;
		}

		$updatedRow = DB::table('a_btns')->where('device_id', '=', -1)
			->where('room_id', '=', $this->roomId)->update(array('auto_wait' => 1, 'edit_type' => URCValues::ETYPE_MACRO, 'popup' => 0, 'activity' => '', 'macro' => '')); 

		return true;
	}

	public function storePowerMacro($auto_wait, $editType, $popup, $activity, $macro) {
		
		$jsonActivity = json_encode($activity);

		if($editType == URCValues::ETYPE_ACTIVITY) {
			
			/*
			$macro_new = array();
			
			//convert to action
			$arActivity = json_decode($jsonActivity);
			foreach($arActivity as $activity) {
				
				$activity->type = URCValues::ACT_DB;
				//$activity->device_id;
				//$activity->func;
				//$activity->repeate_min = ;
				//$activity->repeate_macro = ;

				$macro_new[] = $activity;
			}
			
			$jsonMacro = json_encode($macro_new);
			*/

			//ErrorDebug::write('jsonActivity:'.$jsonActivity);
			//ErrorDebug::write('jsonMacro:'.$jsonMacro);

			$updatedRow = DB::table('a_btns')->where('device_id', '=', -1)
				->where('room_id', '=', $this->roomId)->update(array('auto_wait' => $auto_wait, 'edit_type' => $editType, 'popup' => $popup, 'activity' => $jsonActivity, 'macro' => ''));//$jsonMacro)); 

			return true;
		}
		
		if($editType == URCValues::ETYPE_MACRO){
				
			$jsonMacro = json_encode($macro);

			$updatedRow = DB::table('a_btns')->where('device_id', '=', -1)
				->where('room_id', '=', $this->roomId)->update(array('auto_wait' => $auto_wait, 'edit_type' => $editType, 'popup' => $popup, 'activity' => $jsonActivity, 'macro' => $jsonMacro)); 
			
			return true;
		}
		
		return false;
	}
	
	public function getNewBtnId() {
		
		$device = DB::table('a_devices')->where('id', '=', $this->deviceId)
			->where('room_id', '=', $this->roomId)->first();
		if(!$device) {
			return -1;
		}

		return $device->btn_id_start;
	}

	public function setNewBtnId($newBtnId) {
		
		DB::table('a_devices')->where('id', '=', $this->deviceId)->
			where('room_id', '=', $this->roomId)->update(array('btn_id_start' => $newBtnId));
	}

	protected function isExistBtn($btnId) {

		$existDB = DB::table('a_btns')->where('id', '=', $btnId)
			->where('device_id', '=', $this->deviceId)
			->where('room_id', '=', $this->roomId)->first(); 
		if($existDB) {
			return 1;
		}

		return 0;
	}

	static public function newDBAction($deviceId, $funcId) {

		$act = (object)array('type' => URCValues::ACT_DB, 'device_id' => $deviceId, 'func' => $funcId);
		return $act;
	}
	
	static public function newJumpAction($type, $value) {

		$act = new stdClass;
		$act->type = URCValues::ACT_JUMP;
		$act->to = array('type' => $type, 'value' => $value);

		return $act;
	}

	static public function newDBMacroJSON($deviceId, $funcId) {

		$macro = array();
		$macro[] = URCBtnData::newDBAction($deviceId, $funcId);//array('type' => URCValues::ACT_DB, 'device_id' => $deviceId, 'func' => $funcId);
		return json_encode($macro);
	}

	static public function newJumpMacroJSON($type, $value) {

		$macro = array();
		$macro[] = URCBtnData::newJumpAction($type, $value);
		
		return json_encode($macro);
	}
	
	
	public function newDeviceBtn($btnId, $linkId, $pageId, $pageBtnIdx, $autoWait, $editType, $popup, $imageName, $text, $hiddenOption, &$activityData, &$macroData) {
		DB::table('a_btns')->insert(array('id' => $btnId, 'device_id' => $this->deviceId, 'room_id' => $this->roomId,
		 'link_id' => $linkId, 'page_id' => $pageId, 'page_btn_idx' => $pageBtnIdx, 
		 'auto_wait' => $autoWait, 'edit_type' => $editType, 'popup' => $popup,
		 'image_name' => $imageName, 'display_text' => $text, 'hidden_option' => $hiddenOption, 'activity' => $activityData, 'macro' => $macroData));
	}

	public function newBtnQueryDetail($btnId, $pageId, $pageBtnIdx, $text, $hiddenOption, $autoWait, $editType, $popup, &$activity, &$macroData, $hidden, $pageHidden) {

		$query = array('id' => $btnId, 'device_id' => $this->deviceId, 'room_id' => $this->roomId,
		 'link_id' => -1, 'page_id' => $pageId, 'page_btn_idx' => $pageBtnIdx, 
		 'auto_wait' => $autoWait, 'edit_type' => $editType, 'popup' => $popup,
		 'image_name' => '', 'display_text' => $text, 'hidden_option' => $hiddenOption, 'activity' => $activity, 'macro' => $macroData,
		 'hidden' => $hidden, 'page_hidden' => $pageHidden);

		return $query;
	}

	public function newBtnQuery($btnId, $pageId, $pageBtnIdx, $text, $hiddenOption, &$macroData, $hidden, $pageHidden) {

		$activity = '';
		return $this->newBtnQueryDetail($btnId, $pageId, $pageBtnIdx, $text, $hiddenOption, URCValues::AUTO_WAIT_OFF, URCValues::ETYPE_MACRO,
			URCValues::POPUP_OFF, $activity, $macroData, $hidden, $pageHidden);
	}

	/*
	public function newBtnQuery($btnId, $pageId, $pageBtnIdx, $text, $hiddenOption, &$macroData, $hidden, $pageHidden) {

		$query = array('id' => $btnId, 'device_id' => $this->deviceId, 'room_id' => $this->roomId,
		 'link_id' => -1, 'page_id' => $pageId, 'page_btn_idx' => $pageBtnIdx, 
		 'auto_wait' => URCValues::AUTO_WAIT_OFF, 'edit_type' => URCValues::ETYPE_MACRO, 'popup' => URCValues::POPUP_OFF,
		 'image_name' => '', 'display_text' => $text, 'hidden_option' => $hiddenOption, 'activity' => '', 'macro' => $macroData,
		 'hidden' => $hidden, 'page_hidden' => $pageHidden);

		return $query;
	}
	*/

	public function newBtn($btnId, $pageId, $pageBtnIdx, $text, $hiddenOption, &$macroData) {

		//for doing the bulk query
		$query = $this->newBtnQuery($btnId, $pageId, $pageBtnIdx, $text, $hiddenOption, $macroData, 0, 0);

		DB::table('a_btns')->insert($query);
	}

	public function newHardBtn($btnId, $text, &$macroData) {
		
		$this->newBtn($btnId, -1, -1, $text, 0, $macroData);
	}

	public function newSystemOffBtn() {
		$query = array('id' => URCValues::BTN_SYSTEM_OFF, 'device_id' => $this->deviceId, 'room_id' => $this->roomId,
		 'link_id' => -1, 'page_id' => -1, 'page_btn_idx' => -1, 
		 'auto_wait' => URCValues::AUTO_WAIT_ON, 'edit_type' => URCValues::ETYPE_ACTIVITY, 'popup' => URCValues::POPUP_ON,
		 'image_name' => '', 'display_text' => URCValues::BTN_LABEL_SYSTEM_OFF, 'hidden_option' => 0, 'activity' => '', 'macro' => '');

		DB::table('a_btns')->insert($query);
	}
}


class URCPageData {

	//var $btnArray = null;
	var $roomId = -1;
	var $deviceId = -1;
	//var $curPageId = -1;

	function __construct($roomId, $deviceId) {	

		//$btnArray = null;	
		$this->roomId = $roomId;
		$this->deviceId = $deviceId;
		//$this->curPageId = -1;
	}

	/*
	public function isAddBtn() {

		if(!$this->btnArray || $this->curPageId < 0) {
			if(!$this->btnArray) ErrorDebug::write('isAddBtn NULL BtnArray');
			if($this->curPageId < 0) ErrorDebug::write('isAddBtn curPageId -1');
			return false;
		}

		if(count($this->btnArray) >= 6) {
			ErrorDebug::write('isAddBtn btnArray full');
			return false;
		}

		return true;
	} 
	*/

	public function getNewPageId() {
		
		$device = DB::table('a_devices')->where('id', '=', $this->deviceId)
			->where('room_id', '=', $this->roomId)->first();
		if(!$device) {
			return -1;
		}

		return $device->page_id_start;
	}

	public function setNewPageId($newPageId) {
		
		DB::table('a_devices')->where('id', '=', $this->deviceId)->
			where('room_id', '=', $this->roomId)->update(array('page_id_start' => $newPageId));
	}

	public function getPossibleToAdd(&$pageId, &$pageBtnIdx) {
		
		//check existing pages
		$urcBtns = DB::table('a_btns')->where('device_id', '=', $this->deviceId)-> 
			where('room_id', '=', $this->roomId)->
			whereNotIn('page_id', array(-1))->orderBy('page_id', 'asc')->get();
		
		$arPos = array(-1,-1,-1,-1,-1,-1);
		$curPageId = -2;//-1 is used in db.
		foreach($urcBtns as $btn) {
			
			if($curPageId < 0) {
				$curPageId = $btn->page_id;
				$arPos = array(-1,-1,-1,-1,-1,-1);				
			}
			
			if($btn->page_id == $curPageId) {
				$arPos[$btn->page_btn_idx] = $btn->id;
				continue;
			}
			
			//check
			for($i = 0; $i < 6; $i++) {
				
				if($arPos[$i] >= 0) continue;
				
				$pageId = $curPageId;
				$pageBtnIdx = $i;
				return true;
			}

			$curPageId = $btn->page_id;
			$arPos = array(-1,-1,-1,-1,-1,-1);
			$arPos[$btn->page_btn_idx] = $btn->id;
		}

		//check
		if($curPageId >= 0) {
			for($i = 0; $i < 6; $i++) {
				
				if($arPos[$i] >= 0) continue;
				
				$pageId = $curPageId;
				$pageBtnIdx = $i;
				return true;
			}
		}

		//make new
		$newPageId = $this->getNewPageId();
		$pageId = $newPageId;
		$pageBtnIdx = 0;

		$this->setNewPageId($newPageId+1);

		return true;
	}

	/*
	public function startNewPage() {

		$this->curPageId = $this->getNewPageId();

		ErrorDebug::write('startNewPage : ');
		ErrorDebug::write($this->curPageId);

		//DB::table('a_pages')->insert(array('id' => $this->curPageId, 'device_id' => $this->deviceId, 
		//	'room_id' => $this->roomId, 'btns' => '', 'name' => ''));

		$this->btnArray = array(-1, -1, -1, -1, -1, -1);

		$this->setNewPageId($this->curPageId+1);
	}

	public function saveCurPageBtns() {
		
		if($this->curPageId < 0)
			return false;

		$dataJSON = json_encode($this->btnArray);
		DB::table('a_pages')->where('id', '=', $this->curPageId)->
			where('device_id', '=', $this->deviceId)->
			where('room_id', '=', $this->roomId)->update(array('btns' => $dataJSON));

		ErrorDebug::write('saveCurPageBtns : ');
		ErrorDebug::write($this->curPageId);
		ErrorDebug::write('saveCurPageBtns Data: ');
		ErrorDebug::write($dataJSON);
		return true;
	}
	
	public function getEmptyPosition() {

		if(count($this->btnArray) < 6)
			return -1;

		for($i = 0; $i < 6; $i++) {
			if($this->btnArray[$i] < 0)
				return $i;
		}

		return -1;
	}

	public function newDeviceBtn($btnId, $linkId, $autoWait, $editType, $popup, $imageName, $text, &$activityData, &$macroData) {

		$pos = $this->getEmptyPosition();
		if($pos < 0)
			return false;
		
		$urcBtn = new URCBtnData($this->roomId, $this->deviceId);
		$urcBtn->newDeviceBtn($btnId, $linkId, $this->curPageId, $pos, $autoWait, $editType, $popup, $imageName, $text, $activityData, $macroData);

		$this->btnArray[$pos] = $btnId;
		return true;
	}

	public function newBtn($btnId, $text, &$macroData) {

		$pos = $this->getEmptyPosition();
		if($pos < 0)
			return false;

		$urcBtn = new URCBtnData($this->roomId, $this->deviceId);
		$urcBtn->newBtn($btnId, $this->curPageId, $pos, $text, $macroData);

		$this->btnArray[$pos] = $btnId;
		return true;
	}
	
	public function clearBtnInfo($btnId) {

		$urcPages = DB::table('a_pages')->where('device_id', '=', $this->deviceId)->
			where('room_id', '=', $this->roomId)->get();

		foreach($urcPages as $urcPage) {

			$btns = json_decode($urcPage->btns);
			foreach($btns as $btn) {
				if($btn == $btnId) {
					
					unset($btn);

					$dataJSON = json_encode($btns);
					DB::table('a_pages')->where('id', '=', $urcPage->id)->
						where('device_id', '=', $this->deviceId)->
						where('room_id', '=', $this->roomId)->
						update(array('btns' => $dataJSON));
					
					break;
				}
			}
		}
	}

	public function loadPossibleToAdd() {

		$urcBtns = DB::table('a_btns')->where('device_id', '=', $this->deviceId)-> 
			where('room_id', '=', $this->roomId)->orderBy('page_id', 'desc')->get();

		foreach($urcBtns as $urcPage) {

			$btns = json_decode($urcPage->btns);
			$count = $this->ParseBtnCount($btns);
			if($count >= 6) continue;

			$this->curPageId = $urcPage->id;
			if($count == 0) $this->btnArray = array();
			else $this->btnArray = $btns;

			ErrorDebug::write('loadPossibleToAdd : ');
			ErrorDebug::write($this->curPageId);
			ErrorDebug::write($count);
			if($btns)
				ErrorDebug::write('btns array ok');
			else
				ErrorDebug::write('btns array err');
			if($this->btnArray)
				ErrorDebug::write('array ok');
			else
				ErrorDebug::write('array err');

			return;
		}

		$this->StartNewPage();
	}
	*/

}

class URCDeviceData {

	var $roomId = -1;

	function __construct($roomId) {	
		$this->roomId = $roomId;
	}
	

	public static function isExistVol(&$device) {

		if($device->dev_type == 1) {
			return 0;
		}
		else {
			return 1;
		}

		return 1;
	}

	public function appendPowerOff($deviceId, $addedId) {

		if($addedId < 0)
			return;

		$data = DB::table('a_btns')->where('device_id', '=', -1)
			->where('room_id', '=', $this->roomId)->first();

		$activityData = array();
		if(strlen($data->activity) > 0) {
			$activityData = json_decode($data->activity);			
			if(count($activityData) <= 0) {
				$activityData = array();
			}
		}

		$activityData[] = (object)array('device_id' => $deviceId, 'type' => 0, 'func' => $addedId);
		$jsonActivity = json_encode($activityData);

		DB::table('a_btns')->where('device_id', '=', -1)
			->where('room_id', '=', $this->roomId)->update(array('activity' => $jsonActivity));
	}
	
	//$target = new stdClass;
	//$target->type = 0;
	//$target->addr = "";
	//$target->port = "";
	//$favOption =  new stdClass;
	//$favOption->enable = 0;
	//$favOption->delay = 100;	
	public function createDevice($username, $name, $category, $brand, $model, $dbType, $modelId, $target, $favOption) {

		//get data
		//extract : repeat{min, macro}, 
		$attr = new stdClass;

		$udmlObj = new URCUDMLData($username, 'dev');
		$udmlData = $udmlObj->getDevice($dbType, $modelId, $target->type);
		if(!$udmlData) {
			return -1;
		}
		
		//ErrorDebug::write($dbType.";".$modelId.";".$target->type);

		$attr->repeat_min = $udmlData['attr']['rpt_min'];
		$attr->repeat_macro = $udmlData['attr']['rpt_cnt'];
		
		if(!isset($target->addr)) {
			$target->addr = '';
		} 

		if($target->type === URCValues::DB_TYPE_IP) {//IP

			if(isset($udmlData['attr']['tcp_udp']) && $udmlData['attr']['tcp_udp'] == 1) {
				$target->type = URCValues::DB_TYPE_UDP;
			}

			$attr->ramp_start = $udmlData['attr']['ramp_st'];
			$attr->ramp_speed = $udmlData['attr']['ramp_sp'];
			$attr->auto_cr = $udmlData['attr']['auto_cr'];
			$attr->con_time = $udmlData['attr']['con_time'];
			$attr->delay_after_send = $udmlData['attr']['delay_after_send'];

			if(!isset($target->port)) {
				$target->port = $udmlData['attr']['port'];
			}
		}

		if(!isset($target->port)) {
			$target->port = 0;
		}

		//ErrorDebug::write(json_encode($udmlData));

		//apply data
		$deviceId = -1;
		try
		{
			DB::begintransaction();

			//create device 
			if(strncmp($model, 'Code# ', 6) == 0) {
				$deviceId = $this->newDevice($name, $category, $brand, 'Code# '.$modelId, -1, $udmlData['meta'], $attr, $favOption, $target, 0);
			}
			else {
				$deviceId = $this->newDevice($name, $category, $brand, $model, -1, $udmlData['meta'], $attr, $favOption, $target, 0);
			}
			if($deviceId < 0) {
				throw new \Exception('Device ID not created');
			}
			//create connected Device 
			$this->newConDevData($deviceId, $udmlData);

			//create keyboard data
			$this->newKeyboardData($deviceId, $udmlData);

			//apply hard buttons and pages
			$this->applyBtns($deviceId, $udmlData);
			//add to main page
			if(!$this->addMainBtn($name, $deviceId, $category)) {
				throw new \Exception('fail to add device button');
			}

			//apply power off
			$addedId = -1;
			if($udmlData['meta']) {
				foreach($udmlData['meta'] as $item) {
					if($item['strid'] == 'POWER_OFF') {
						$addedId = (int)$item['funcid'];
					}
					else if($item['strid'] == 'POWER_TOGGLE') {
						if($addedId < 0) {
							$addedId = (int)$item['funcid'];
						}
					}
				}
			}
			$this->appendPowerOff($deviceId, $addedId);
			DB::commit();
		}
		catch(\Exception $e) 
		{
			DB::rollback();
			$deviceId = -1;		
		}

		return $deviceId;
	}


	public function createCustomDevice(&$deviceData) {
		
		//get data
		//extract : repeat{min, macro}, 
		
		$favOption = new stdClass;
		$favOption->enable = 0;
		$favOption->delay = 400;
		$favOption->enter = 1;

		$jsonDevData = json_encode($deviceData);
		//ErrorDebug::write('createCustom');
		//ErrorDebug::write($jsonDevData);
		
		$device = json_decode($jsonDevData);
		
		$attr = new stdClass;
		$attr->repeat_min = $device->repeat->min;
		$attr->repeat_macro = $device->repeat->macro;
		$attr->con_time = 0;
		if(isset($device->attr->con_time)) {
			$attr->con_time = $device->attr->con_time;
		}

		$metaData = array();
		if(isset($device->meta_pwr_on)) {
			$metaData[] = array('strid' => 'POWER_ON', 'funcid' => $device->meta_pwr_on);
		}
		if(isset($device->meta_pwr_off)) {
			$metaData[] = array('strid' => 'POWER_OFF', 'funcid' => $device->meta_pwr_off);
		}
		if(isset($device->meta_pwr_toggle)) {
			$metaData[] = array('strid' => 'POWER_TOGGLE', 'funcid' => $device->meta_pwr_toggle);
		}
		if(isset($device->meta_in_toggle)) {
			$metaData[] = array('strid' => 'INPUT_TOGGLE', 'funcid' => $device->meta_in_toggle);
		}

		/*
		$attr->ramp_start = $udmlData->attr->ramp_start;
		$attr->ramp_speed = $udmlData->attr->ramp_speed;
		
		$target->type = URCValues::DB_TYPE_UDP;
		$attr->auto_cr = $udmlData->attr->auto_cr;
		*/


		//apply data
		$deviceId = -1;
		try
		{
			DB::begintransaction();

			//create device 
			//$metaData = null;
			$deviceId = $this->newDevice($device->name, $device->category, $device->brand, $device->model, -1, $metaData, $attr, $favOption, $device->target, 0);
			if($deviceId < 0) {
				throw new \Exception('Device ID not created');
			}

			//create connected Device 
			if(isset($device->dbCon)) {
				$this->newCustomConDevData($deviceId, $device->dbCon);
			}

			//create keyboard data
			if(isset($device->dbKey)) {
				$this->newCustomKeyboardData($deviceId, $device->dbKey);
			}

			//apply hard buttons and pages
			$this->applyCustomBtns($deviceId, $device);

			//add to main page
			if(!$this->addMainBtn($device->name, $deviceId, $device->category)) {
				throw new \Exception('fail to add device button');
			}

			//apply power off
			$addedId = -1;
			foreach($metaData as $item) {
				if($item['strid'] == 'POWER_OFF') {
					$addedId = (int)$item['funcid'];
				}
				else if($item['strid'] == 'POWER_TOGGLE') {
					if($addedId < 0) {
						$addedId = (int)$item['funcid'];
					}
				}
			}

			$this->appendPowerOff($deviceId, $addedId);


			DB::commit();
		}
		catch(\Exception $e) 
		{
			DB::rollback();
			$deviceId = -1;		
		}

		return $deviceId;
	}

	public function createTwowayDevice($username, $name, $model, $modelId, $target) {

		
		//create device 
		$attr = new stdClass;

		$udmlObj = new URCUDMLData($username, 'dev');

		$dbType = 0;
		$dbTargetType = URCValues::DB_TYPE_IP;
		switch($model)
		{
		case "SNP-2":
			break;
		default:
			return -1;
		}

		$udmlData = $udmlObj->getDevice($dbType, $modelId, $dbTargetType);
		if($udmlData) {
			$attr->repeat_min = $udmlData['attr']['rpt_min'];
			$attr->repeat_macro = $udmlData['attr']['rpt_cnt'];
		
			if(!isset($target->addr)) {
				$target->addr = '';
			} 
		}
		else {
			$attr->repeat_min = 3;
			$attr->repeat_macro = 3;

			return -1;
		}

		if($dbTargetType === URCValues::DB_TYPE_IP) {//IP

			/*
			if(isset($udmlData['attr']['tcp_udp']) && $udmlData['attr']['tcp_udp'] == 1) {
				$target->type = URCValues::DB_TYPE_UDP;
			}
			*/

			$attr->ramp_start = $udmlData['attr']['ramp_st'];
			$attr->ramp_speed = $udmlData['attr']['ramp_sp'];
			$attr->auto_cr = $udmlData['attr']['auto_cr'];
			$attr->con_time = $udmlData['attr']['con_time'];
			$attr->delay_after_send = $udmlData['attr']['delay_after_send'];

			if(!isset($target->port)) {
				$target->port = $udmlData['attr']['port'];
			}
		}
		
		$favOption =  new stdClass;
		$favOption->enable = 0;
		$favOption->delay = 100;
		$favOption->enter = 1;

		$deviceId = -1;
		try
		{
			DB::begintransaction();

			//create device 
			$metaData = $udmlData ? $udmlData['meta'] : null;			
			$deviceId = $this->newDevice($name, '', '', $model, $modelId, $metaData, $attr, $favOption, $target, 1);			
			if($deviceId < 0) {
				throw new \Exception('Device ID not created');
			}
	
			if($udmlData) {
				//create connected Device 
				$this->newConDevData($deviceId, $udmlData);

				//create keyboard data
				$this->newKeyboardData($deviceId, $udmlData);
			}

			//apply hard buttons and pages
			//$this->applyBtns($deviceId, $udmlData);

			//add to main page
			if(!$this->addMainBtn($name, $deviceId, $model)) {
				throw new \Exception('fail to add device button');
			}

			//apply power off
			$addedId = -1;
			if($udmlData['meta']) {
				foreach($udmlData['meta'] as $item) {
					if($item['strid'] == 'POWER_OFF') {
						$addedId = (int)$item['funcid'];
					}
					else if($item['strid'] == 'POWER_TOGGLE') {
						if($addedId < 0) {
							$addedId = (int)$item['funcid'];
						}
					}
				}
			}

			$this->appendPowerOff($deviceId, $addedId);

			DB::commit();
		}
		catch(\Exception $e) 
		{
			DB::rollback();
			$deviceId = -1;		
		}

		return $deviceId;
	}

	/*
	public function createTwowayDevice($name, $model, $target) {

		
		//apply data
		$deviceId = -1;
		try
		{
			DB::begintransaction();

			//create device 
			$attr = new stdClass;
			$attr->repeat_min = 3;
			$attr->repeat_macro = 3;
			
			$favOption =  new stdClass;
			$favOption->enable = 0;
			$favOption->delay = 100;
			$favOption->enter = 1;

			$metaData = null;
			$deviceId = $this->newDevice($name, '', '', $model, $metaData, $attr, $favOption, $target, 1);
			if($deviceId < 0) {
				throw new \Exception('Device ID not created');
			}
			
			//add to main page
			if(!$this->addMainBtn($name, $deviceId, $model)) {
				throw new \Exception('fail to add device button');
			}

			DB::commit();
		}
		catch(\Exception $e) 
		{
			DB::rollback();
			$deviceId = -1;		
		}

		return $deviceId;
	}
	*/

	public function destroyDevice($deviceId) {

		try
		{
			DB::begintransaction();

			//delete device 
			DB::table('a_devices')->where('room_id', '=', $this->roomId)->
				where('id', '=', $deviceId)->delete();
			
			//delete connected Device 
			DB::table('a_keys_db')->where('room_id', '=', $this->roomId)->
				where('device_id', '=', $deviceId)->delete();

			//delete keyboard data
			DB::table('a_con_db')->where('room_id', '=', $this->roomId)->
				where('device_id', '=', $deviceId)->delete();
			
			//delete pages and btns
			//DB::table('a_pages')->where('room_id', '=', $this->roomId)->
			//	where('device_id', '=', $deviceId)->delete();

			DB::table('a_btns')->where('room_id', '=', $this->roomId)->
				where('device_id', '=', $deviceId)->delete();

			//delete from main page
			$this->deleteDeviceBtn($deviceId);

			//clear punch info
			$this->clearPunchInfo($deviceId);

			DB::commit();
		}
		catch(\Exception $e) 
		{
			DB::rollback();
			return false;		
		}

		return true;
	}

	public function editDevice($deviceId, $deviceName, $target, $attr) {

		try
		{
			DB::begintransaction();

			//con_time is not set, it is now showed in User side
			if($target->type == URCValues::DB_TYPE_IP ||
				$target->type == URCValues::DB_TYPE_UDP) {
				$updatedRow = DB::table('a_devices')->where('room_id', '=', $this->roomId)->
					where('id', '=', $deviceId)->update(
						array('name' => $deviceName, 'target_type' => $target->type, 'target_addr' => $target->addr, 'target_port' => $target->port,
						'repeat_min' => $attr->repeat_min, 'repeat_macro' => $attr->repeat_macro,
						'ramp_start' => $attr->ramp_start, 'ramp_speed' => $attr->ramp_speed, 'auto_cr' => $attr->auto_cr));
			}
			else {
				$updatedRow = DB::table('a_devices')->where('room_id', '=', $this->roomId)->
					where('id', '=', $deviceId)->update(
						array('name' => $deviceName, 'target_type' => $target->type, 'target_addr' => $target->addr, 'target_port' => $target->port,
						'repeat_min' => $attr->repeat_min, 'repeat_macro' => $attr->repeat_macro));
			}
		
			DB::table('a_btns')->where('room_id', '=', $this->roomId)->
				where('link_id', '=', $deviceId)->update(array('display_text' => $deviceName));

			DB::commit();
		}
		catch(\Exception $e) 
		{
			DB::rollback();
			return false;
		}
		
		return true;
	}

	public function setFavoriteDevice($deviceId, $favOption, $favDelayOption, $favDelay = 400, $favEnter = 1) {

		$updatedRow = 0;
	
		if($favDelayOption == URCValues::FAV_DELAY_KEEP) {
		
			$updatedRow = DB::table('a_devices')->where('room_id', '=', $this->roomId)->
				where('id', '=', $deviceId)->update(array('fav_option' => $favOption, 'fav_enter' => $favEnter));			
		}
		else {
			$updatedRow = DB::table('a_devices')->where('room_id', '=', $this->roomId)->
				where('id', '=', $deviceId)->update(array('fav_option' => $favOption, 'fav_delay' => $favDelay, 'fav_enter' => $favEnter));
		}
		
		if($updatedRow <= 0)
			return false;
		
		return true;
	}

	
	public function getPunchDevice($deviceId) {

		$device = DB::table('a_devices')->where('room_id', '=', $this->roomId)->
				where('id', '=', $deviceId)->first();	

		if(!$device)
			return -1;

		return $device->punch_vol;
	}

	public function setPunchDevice($deviceFrom, $deviceTo) {

		if($deviceFrom == $deviceTo) {
			$deviceFrom = -1;
		}
		
		$updatedRow = DB::table('a_devices')->where('room_id', '=', $this->roomId)->
				where('id', '=', $deviceTo)->update(array('punch_vol' => (int)$deviceFrom));		

		//if($updatedRow <= 0)
		//	return false;

		return true;
	}

	public function setPunchDevices($deviceFrom, $deviceTo) {

		$jsonData = json_encode($deviceTo);
		$devices = json_decode($jsonData);

		if(!is_array($devices)) {
			return false;
		}

		try
		{
			DB::begintransaction();

			foreach($devices as $item) {

				if($item == $deviceFrom) {

					DB::table('a_devices')->where('room_id', '=', $this->roomId)->
						where('id', '=', $item)->update(array('punch_vol' => -1));
				}
				else {
							
					DB::table('a_devices')->where('room_id', '=', $this->roomId)->
						where('id', '=', $item)->update(array('punch_vol' => (int)$deviceFrom));
				}
			}

			DB::commit();
		}
		catch(\Exception $e) 
		{
			DB::rollback();
			return false;
		}
		
		return true;
	}

	public function newMainDevice() {

		$attr = new stdClass;
		$attr->repeat_min = 3;
		$attr->repeat_macro = 3;

		$target = new stdClass;
		$target->type = 0;
		$target->addr = '';
		$target->port = 0;
		
		$favOption =  new stdClass;
		$favOption->enable = 0;
		$favOption->delay = 100;
		$favOption->enter = 1;

		$metaData = null;
		$deviceId = $this->newDevice("Main", "Main", "", "", -1, $metaData, $attr, $favOption, $target, 0);
		
		return $deviceId;
	}

	public function repairMainDevice($mainDevId) {

		$name = "Main";
		$category = "Main";
		$brand = "";
		$model = "";

		$modelId = -1;

		$devType = 0;

		$attr = new stdClass;
		$attr->repeat_min = 3;
		$attr->repeat_macro = 3;

		$target = new stdClass;
		$target->type = 0;
		$target->addr = '';
		$target->port = 0;
		
		$favOption =  new stdClass;
		$favOption->enable = 0;
		$favOption->delay = 100;
		$favOption->enter = 1;

		$deviceId = $mainDevId;
		if($deviceId < 0)
			return -1;

		//check already exist
		if($this->isExistDevice($deviceId))
			return -1;

		$ramp_start = 100;
		$ramp_speed = 100;
		$auto_cr = 0;	
		$con_time = 0;	
		$delay_after_send = 50;
		switch($target->type) {
		case URCValues::DB_TYPE_IP:
		case URCValues::DB_TYPE_UDP:
		case URCValues::DB_TYPE_MAC:

			$repeat_min = 1;
			$repeat_macro = 1;
			if(isset($attr->repeat_min)) {
				$repeat_min = $attr->repeat_min;
			}
			if(isset($attr->repeat_macro)) {
				$repeat_macro = $attr->repeat_macro;
			}
			if(isset($attr->ramp_start)) {
				$ramp_start = $attr->ramp_start;
			}
			if(isset($attr->ramp_speed)) {
				$ramp_speed = $attr->ramp_speed;
			}
			if(isset($attr->auto_cr)) {
				$auto_cr = $attr->auto_cr;
			}
			if(isset($attr->con_time)) {
				$con_time = $attr->con_time;
			}
			if(isset($attr->delay_after_send)) {
				$delay_after_send = $attr->delay_after_send;
			}
			break;
		//case URCValues::DB_TYPE_IR:
		default:

			$repeat_min = 3;
			$repeat_macro = 3;		
			if(isset($attr->repeat_min)) {
				$repeat_min = $attr->repeat_min;
			}
			if(isset($attr->repeat_macro)) {
				$repeat_macro = $attr->repeat_macro;
			}
			break;
		}

		$metaPwrOn = -1;
		$metaPwrOff = -1;
		$metaPwrToggle = -1;
		$metaInToggle = -1;

		//ErrorDebug::write('on:'.$metaPwrOn.'off:'.$metaPwrOff.'toggle:'.$metaPwrToggle.'in:'.$metaInToggle);
		//ErrorDebug::write('recover_mainDev'.$deviceId);
		//add
		DB::table('a_devices')->insert(array('id' => $deviceId, 'room_id' => $this->roomId, 
			'dev_type' => $devType,
			'category' => $category, 'brand' => $brand, 'model' => $model, 'model_id' => $modelId, 'page_id_start' => 0, 'btn_id_start' => 8192,//0x2000 
			'punch_vol' => -1, 'repeat_min' => $repeat_min, 'repeat_macro' => $repeat_macro,
			'ramp_start' => $ramp_start, 'ramp_speed' => $ramp_speed, 'con_time' => $con_time, 'delay_after_send' => $delay_after_send, 
			'fav_option' => $favOption->enable, 'fav_delay' => $favOption->delay, 'fav_enter' => $favOption->enter, 
			'name' => $name, 'target_type' => $target->type, 'target_addr' => $target->addr, 'target_port' => $target->port,
			'auto_cr' => $auto_cr,
			'meta_pwr_on' => $metaPwrOn, 'meta_pwr_off' => $metaPwrOff, 'meta_pwr_toggle' => $metaPwrToggle, 'meta_in_toggle' => $metaInToggle));
		
		return $deviceId;
	}


	public function newDevice($name, $category, $brand, $model, $modelId, &$metaData, &$attr, &$favOption, &$target, $devType) {

		$deviceId = $this->getNewDeviceId();
		if($deviceId < 0)
			return -1;
		$this->setNewDeviceId($deviceId+1);//DB::table('a_rooms')->where('id', '=', $roomId)->update(array('device_id_start' => $deviceId+1));

		//check already exist
		if($this->isExistDevice($deviceId))
			return -1;

		$ramp_start = 100;
		$ramp_speed = 100;
		$auto_cr = 0;	
		$con_time = 0;	
		$delay_after_send = 50;
		switch($target->type) {
		case URCValues::DB_TYPE_IP:
		case URCValues::DB_TYPE_UDP:
		case URCValues::DB_TYPE_MAC:

			$repeat_min = 1;
			$repeat_macro = 1;
			if(isset($attr->repeat_min)) {
				$repeat_min = $attr->repeat_min;
			}
			if(isset($attr->repeat_macro)) {
				$repeat_macro = $attr->repeat_macro;
			}
			if(isset($attr->ramp_start)) {
				$ramp_start = $attr->ramp_start;
			}
			if(isset($attr->ramp_speed)) {
				$ramp_speed = $attr->ramp_speed;
			}
			if(isset($attr->auto_cr)) {
				$auto_cr = $attr->auto_cr;
			}
			if(isset($attr->con_time)) {
				$con_time = $attr->con_time;
			}
			if(isset($attr->delay_after_send)) {
				$delay_after_send = $attr->delay_after_send;
			}
			break;
		//case URCValues::DB_TYPE_IR:
		default:

			$repeat_min = 3;
			$repeat_macro = 3;		
			if(isset($attr->repeat_min)) {
				$repeat_min = $attr->repeat_min;
			}
			if(isset($attr->repeat_macro)) {
				$repeat_macro = $attr->repeat_macro;
			}
			break;
		}

		$metaPwrOn = -1;
		$metaPwrOff = -1;
		$metaPwrToggle = -1;
		$metaInToggle = -1;
		if($metaData) {
			foreach($metaData as $item) {
				if($item['strid'] == 'POWER_ON') {
					$metaPwrOn = $item['funcid'];
				}
				else if($item['strid'] == 'POWER_OFF') {
					$metaPwrOff = $item['funcid'];
				}
				else if($item['strid'] == 'POWER_TOGGLE') {
					$metaPwrToggle = $item['funcid'];
				}
				else if($item['strid'] == 'INPUT_TOGGLE') {
					$metaInToggle = $item['funcid'];
				}
			}
		}

		//ErrorDebug::write('on:'.$metaPwrOn.'off:'.$metaPwrOff.'toggle:'.$metaPwrToggle.'in:'.$metaInToggle);

		//add
		DB::table('a_devices')->insert(array('id' => $deviceId, 'room_id' => $this->roomId, 
			'dev_type' => $devType,
			'category' => $category, 'brand' => $brand, 'model' => $model, 'model_id' => $modelId, 'page_id_start' => 0, 'btn_id_start' => 8192,//0x2000 
			'punch_vol' => -1, 'repeat_min' => $repeat_min, 'repeat_macro' => $repeat_macro,
			'ramp_start' => $ramp_start, 'ramp_speed' => $ramp_speed, 'con_time' => $con_time, 'delay_after_send' => $delay_after_send, 
			'fav_option' => $favOption->enable, 'fav_delay' => $favOption->delay, 'fav_enter' => $favOption->enter, 
			'name' => $name, 'target_type' => $target->type, 'target_addr' => $target->addr, 'target_port' => $target->port,
			'auto_cr' => $auto_cr,
			'meta_pwr_on' => $metaPwrOn, 'meta_pwr_off' => $metaPwrOff, 'meta_pwr_toggle' => $metaPwrToggle, 'meta_in_toggle' => $metaInToggle));
		
		return $deviceId;
	}

	public function getNewDeviceId() {
		
		$room = DB::table('a_rooms')->where('id', '=', $this->roomId)->first();
		if(!$room) {
			return -1;
		}

		return $room->device_id_start;
	}

	public function setNewDeviceId($newDeviceId) {
		
		DB::table('a_rooms')->where('id', '=', $this->roomId)->update(array('device_id_start' => $newDeviceId));
	}

	public function isExistDevice($deviceId) {

		$existDB = DB::table('a_devices')->where('id', '=', $deviceId)->
			where('room_id', '=', $this->roomId)->first(); 
		if($existDB) {
			return 1;
		}
		return 0;
	}

	protected function newConDevData($deviceId, $udmlData) {
		
		//for doing the bulk query
		$query = array();
		foreach($udmlData['btns'] as $btn) {

			$query[] = array('id' => (int) $btn['id'], 'device_id' => $deviceId, 'room_id' => $this->roomId, 
				'name' => $btn['caption'], 'type' => URCValues::IR_PREPROGRAM, 'data' => $btn['cmd']);
		}

		if(count($query) > 0) {
			DB::table('a_con_db')->insert($query);
		}
		
		/*
		foreach($udmlData['btns'] as $btn) {

			DB::table('a_con_db')->insert(array('id' => $btn->value, 'device_id' => $deviceId, 'room_id' => $this->roomId, 
				'name' => $btn->label, 'data' => $btn->data));
		}
		*/		
	}

	protected function newCustomConDevData($deviceId, $dbCon) {
		
		//for doing the bulk query
		$query = array();
		foreach($dbCon as $func) {

			$query[] = array('id' => (int) $func->id, 'device_id' => $deviceId, 'room_id' => $this->roomId, 
				'name' => $func->name, 'type' => $func->type, 'data' => $func->data);

		}

		if(count($query) > 0) {
			DB::table('a_con_db')->insert($query);
		}
	}

	public function getConDevData($deviceId) {

		return DB::table('a_con_db')->where('device_id', '=', $deviceId)->
			where('room_id', '=', $this->roomId)->get();
	}

	public function getMetaData($deviceId) {

		$urcDevice = DB::table('a_devices')->where('room_id', '=', $this->roomId)->
			where('id', '=', $deviceId)->first(); 
		if(!$urcDevice) {
			return false;
		}

		return $urcDevice;
	}

	protected function newKeyboardData($deviceId, $udmlData) {

		//for doing the bulk query
		$query = array();
		foreach($udmlData['keys'] as $btn) {

			$query[] = array('id' => $btn['def'], 'device_id' => $deviceId, 'room_id' => $this->roomId, 
				'name' => $btn['caption'], 'type' => URCValues::IR_PREPROGRAM, 'data' => $btn['cmd']);
		}
		if(count($query) > 0) {
			DB::table('a_keys_db')->insert($query);
		}
		/*
		foreach($udmlData['keys'] as $btn) {

			DB::table('a_keys_db')->insert(array('id' => $btn->value, 'device_id' => $deviceId, 'room_id' => $this->roomId, 
				'name' => $btn->label, 'data' => $btn->data));
		}
		*/		
	}

	protected function newCustomKeyboardData($deviceId, $dbKey) {

		//for doing the bulk query
		$query = array();
		foreach($dbKey as $func) {

			$query[] = array('id' => $func->id, 'device_id' => $deviceId, 'room_id' => $this->roomId, 
				'name' => $func->name, 'type' => $func->type, 'data' => $func->data);
		}
		if(count($query) > 0) {
			DB::table('a_keys_db')->insert($query);
		}
	}


	public function applyBtns($deviceId, $udmlData) {
		
		if(isset($udmlData['attr']['last_page'])) {

			$urcBtn = new URCBtnData($this->roomId, $deviceId);
			$btn_id_start = $urcBtn->getNewBtnId();
			$btn_id_start_org = $btn_id_start;

			$conData = $this->getConDevData($deviceId);
		
			$urcPage = new URCPageData($this->roomId, $deviceId);
			
			//for doing the bulk query
			$query = array();
			foreach($udmlData['btns'] as $btn) {

				$btnId = $btn['id'];
				$macroData = URCBtnData::newDBMacroJSON($deviceId, (int)$btnId);

				$isHardBtn = URCUDMLData::isHardKeyId($btnId);
				if($isHardBtn) {			
					$query[] = $urcBtn->newBtnQuery($btnId, -1, -1, $btn['caption'], 0, $macroData, 0, 0);
				}

				if(isset($btn['pg_num']) && isset($btn['btn_num'])) {

					$pageId = ((int)$btn['pg_num']) - 1;
					$pageBtnIdx = ((int)$btn['btn_num']) - 1;

					//ErrorDebug::write('lcd'.$pageId.'     '.$pageBtnIdx);				
					$query[] = $urcBtn->newBtnQuery($btn_id_start, $pageId, $pageBtnIdx, $btn['caption'], 0, $macroData, 0, 0);
					$btn_id_start++;
				}
			}

			if(count($query) > 0) {
				DB::table('a_btns')->insert($query);
			}

			if($btn_id_start_org != $btn_id_start) {//added

				$new_page_id = $udmlData['attr']['last_page'];
				//ErrorDebug::write('$new_page_id'.$new_page_id);
				$urcPage->setNewPageId($new_page_id);
				$urcBtn->setNewBtnId($btn_id_start);
			}
		}
		else {
		
			$urcBtn = new URCBtnData($this->roomId, $deviceId);
			$btn_id_start = $urcBtn->getNewBtnId();
			
			$conData = $this->getConDevData($deviceId);
		
			$urcPage = new URCPageData($this->roomId, $deviceId);
			$pageId = $urcPage->getNewPageId();
			$pageBtnIdx = 0;
			
			//for doing the bulk query
			$query = array();
			foreach($conData as $funcData) {

				$macroData = URCBtnData::newDBMacroJSON($deviceId, $funcData->id);

				if(URCUDMLData::isHardKeyId($funcData->id)) {			
					$urcBtn->newHardBtn($funcData->id, $funcData->name, $macroData);
				}
				else {
					if($pageBtnIdx >= 6) {
						$pageBtnIdx = 0;
						$pageId++;
					}
					
					$query[] = $urcBtn->newBtnQuery($btn_id_start, $pageId, $pageBtnIdx, $funcData->name, 0, $macroData, 0, 0);
					$btn_id_start++;
					$pageBtnIdx++;
				}
			}

			if(count($query) > 0) {
				DB::table('a_btns')->insert($query);
			}

			if($pageBtnIdx > 0)//added
				$urcPage->setNewPageId($pageId+1);
			else
				$urcPage->setNewPageId($pageId);
			
			$urcBtn->setNewBtnId($btn_id_start);
		}
	}

	public function applyCustomBtns($deviceId, &$device) {
		
		/*
		$query = array();

		//apply hard buttons and pages
		$new_page_id = 0;
		$btn_id_max = 8192;//0x2000
		$urcBtn = new URCBtnData($this->roomId, $deviceId);				
		foreach($device->pages as $page) {

			foreach($page->btns as $btn) {

				$btnMacro = json_decode($btn->macro);
				foreach($btnMacro as $func) {
					if($func->device_id < 0) {
						$func->device_id = $deviceId;
					}
				}
				$btn->macro = json_encode($btnMacro);

				$query[] = $urcBtn->newBtnQuery($btn->id, $new_page_id, $btn->page_btn_idx, $btn->display_text, $btn->hidden_option, $btn->macro);				
				if($btn_id_max <= $btn->id) {
					$btn_id_max = $btn->id+1;
				}
			}

			$new_page_id++;
		}

		//ErrorDebug::write(json_encode($query));

		if(count($query)) {
			DB::table('a_btns')->insert($query);
		}

		//set new btn id
		$urcBtn->setNewBtnId($btn_id_max);
		
		//apply new page id
		$urcPage = new URCPageData($this->roomId, $deviceId);
		$urcPage->setNewPageId($new_page_id);
		*/


		//add
		$query = array();

		$urcBtn = new URCBtnData($this->roomId, $deviceId);
		$btn_id_start = $urcBtn->getNewBtnId();

		$new_page_id = 0;
		foreach($device->pages as $page) {

			if($page->id < 0) {
				foreach($page->btns as $btn) {

					$btnMacro = json_decode($btn->macro);
					foreach($btnMacro as $func) {
						if($func->device_id < 0) {
							$func->device_id = $deviceId;
						}
					}
					$btn->macro = json_encode($btnMacro);
				
					$query[] = $urcBtn->newBtnQuery($btn->id, $page->id, $btn->page_btn_idx, $btn->display_text, $btn->hidden_option, $btn->macro, 0, 0);
				}
			}
			else {
				foreach($page->btns as $btn) {

					$btnMacro = json_decode($btn->macro);
					foreach($btnMacro as $func) {
						if($func->device_id < 0) {
							$func->device_id = $deviceId;
						}
					}
					$btn->macro = json_encode($btnMacro);

					$query[] = $urcBtn->newBtnQuery($btn_id_start, $page->id, $btn->page_btn_idx, $btn->display_text, $btn->hidden_option, $btn->macro, 0, 0);
					$btn_id_start++;
				}

				if($new_page_id <= $page->id) {
					$new_page_id = $page->id + 1;
				}
			}
		}

		if(count($query)) {
			DB::table('a_btns')->insert($query);
		}

		//set new btn id
		$urcBtn->setNewBtnId($btn_id_start);

		//apply new page id
		$urcPage = new URCPageData($this->roomId, $deviceId);
		$urcPage->setNewPageId($new_page_id);

		//ErrorDebug::write('new_page_id'.$new_page_id);
	}


	public function getMainDeviceId() {

		$room = DB::table('a_rooms')->where('id', '=', $this->roomId)->first();
		if(!$room)
			return -1;

		return $room->main_device_id;
	}

	/*
	public function getMainDevice() {

		$mainDevId = $this->getMainDeviceId();
		if($mainDevId < 0)
			return false;

		$masterDev = DB::table('a_devices')->where('room_id', '=', $this->roomId)->
			where('id', '=', $mainDevId)->first(); 
		
		return $masterDev;
	}
	*/

	public function getDefaultImage($category) {

		$udmlObj = new URCUDMLData('', 'dev');
		return $udmlObj->getDefaultImage($category);
		/*
		$category = str_replace('&', '', $category);
		return strtoupper($category);
		*/
	}

	public function addMainBtn($name, $addedDeviceId, $addedCategory) {

		$mainDevId = $this->getMainDeviceId();
		if($mainDevId < 0)
			return false;

		$urcBtn = new URCBtnData($this->roomId, $mainDevId);
		$btn_id_start = $urcBtn->getNewBtnId();
		$urcBtn->setNewBtnId($btn_id_start+1);

		$urcPage = new URCPageData($this->roomId, $mainDevId);

		$pageId = -1;
		$pageBtnIdx = -1;
		if(!$urcPage->getPossibleToAdd($pageId, $pageBtnIdx))
			return false;

		$imageName = $this->getDefaultImage($addedCategory);
		$activityData = '';
		$macroData = '';//URCBtnData::newJumpMacroJSON(URCValues::JUMP_DEVICE, $addedDeviceId);		
		$urcBtn->newDeviceBtn($btn_id_start, $addedDeviceId, 
			$pageId, $pageBtnIdx,
			URCValues::AUTO_WAIT_ON, URCValues::ETYPE_MACRO, URCValues::POPUP_ON, 
			$imageName, $name, 0, $activityData, $macroData);
		
		//$urcPage->saveCurPageBtns();

		
		
		return true;
	}

	public function addMainBtnForTwowayDevice($name, $addedDeviceId, $model) {

		$mainDevId = $this->getMainDeviceId();
		if($mainDevId < 0)
			return false;

		$urcBtn = new URCBtnData($this->roomId, $mainDevId);
		$btn_id_start = $urcBtn->getNewBtnId();
		$urcBtn->setNewBtnId($btn_id_start+1);
		
		$urcPage = new URCPageData($this->roomId, $mainDevId);

		$pageId = -1;
		$pageBtnIdx = -1;
		if(!$urcPage->getPossibleToAdd($pageId, $pageBtnIdx))
			return false;

		$imageName = '';//$this->getDefaultImage($addedCategory);
		$activityData = '';
		$macroData = '';//URCBtnData::newJumpMacroJSON(URCValues::JUMP_DEVICE, $addedDeviceId);		
		$urcBtn->newDeviceBtn($btn_id_start, $addedDeviceId, 
			$pageId, $pageBtnIdx,
			URCValues::AUTO_WAIT_ON, URCValues::ETYPE_MACRO, URCValues::POPUP_ON, 
			$imageName, $name, 0, $activityData, $macroData);
		
		//$btn_id_start++;
		
		//$urcPage->saveCurPageBtns();

		
		return true;
	}

	public function deleteDeviceBtn($deviceId) {

		/*
		$mainDevice = $this->getMainDevice();
		if(!$mainDevice)
			return false;

		$btns = DB::table('a_btns')->where('room_id', '=', $this->roomId)->
			where('link_id', '=', $deviceId)->get();
		if(!$btns)
			return false;

		foreach($btns as $btn) {
			
			if($btn->device_id != $mainDevice->id) {//for debug
				return false;
			}

			$urcPage = new URCPageData($this->roomId, $mainDevice->id);
			$urcPage->clearBtnInfo($btn->id);
		}
		*/

		DB::table('a_btns')->where('room_id', '=', $this->roomId)->
			where('link_id', '=', $deviceId)->delete();

		return true;
	}

	public function clearPunchInfo($deviceId) {

		DB::table('a_devices')->where('room_id', '=', $this->roomId)->
			where('punch_vol', '=', $deviceId)->update(array('punch_vol' => -1));		

		DB::table('a_twoway_devices')->where('room_id', '=', $this->roomId)->
			where('punch_vol', '=', $deviceId)->update(array('punch_vol' => -1));	
	}

	public function getConDevFuncs($deviceId) {
		$condevs = DB::table('a_con_db')->where('room_id', '=', $this->roomId)->
			where('device_id', '=', $deviceId)->get();

		unset($condevs['device_id']);

		return $condevs;
	}

	public function getDevice($deviceId, $isMain) {

		$urcDevice = DB::table('a_devices')->where('room_id', '=', $this->roomId)->
			where('id', '=', $deviceId)->first(); 
		if(!$urcDevice) {
			return false;
		}

		$urcDevice->exist_vol = URCDeviceData::isExistVol($urcDevice);

		if($urcDevice->dev_type == 1) {
			
			$deviceObj = new stdClass;
			$deviceObj->name = $urcDevice->name;
			$deviceObj->id = $deviceId;
			$deviceObj->dev_type = $urcDevice->dev_type;

			return $deviceObj;	
		}

		$urcBtns = DB::table('a_btns')->where('device_id', '=', $deviceId)-> 
			where('room_id', '=', $this->roomId)->orderBy('page_id', 'asc')->orderBy('page_btn_idx', 'asc')->get();

		$urcConDB = DB::table('a_con_db')->where('device_id', '=', $deviceId)-> 
			where('room_id', '=', $this->roomId)->get();

		$urcKeyDB = DB::table('a_keys_db')->where('device_id', '=', $deviceId)-> 
			where('room_id', '=', $this->roomId)->get();

		$deviceObj = new stdClass;
		$deviceObj->name = $urcDevice->name;
		$deviceObj->id = $deviceId;
		$deviceObj->dev_type = $urcDevice->dev_type;
		$deviceObj->meta_pwr_on = $urcDevice->meta_pwr_on;
		$deviceObj->meta_pwr_off = $urcDevice->meta_pwr_off;
		$deviceObj->meta_pwr_toggle = $urcDevice->meta_pwr_toggle;
		$deviceObj->meta_in_toggle = $urcDevice->meta_in_toggle;

		$deviceObj->pages = array();	

		if($isMain === false) {
			
			$deviceObj->repeat = new stdClass;
			$deviceObj->repeat->min = $urcDevice->repeat_min;
			$deviceObj->repeat->macro = $urcDevice->repeat_macro;
			if($urcConDB) {
				$deviceObj->dbCon = $urcConDB;
			}
			else {
				$deviceObj->dbCon = array();
			}

			if($urcKeyDB) {
				$deviceObj->dbKey = $urcKeyDB;
			}
			else {
				$deviceObj->dbKey = array();
			}

			$deviceObj->type = $urcDevice->target_type;
			if($deviceObj->type == URCValues::DB_TYPE_IP ||
				$deviceObj->type == URCValues::DB_TYPE_UDP) {

				$deviceObj->ramp = new stdClass;
				$deviceObj->ramp->start = $urcDevice->ramp_start;
				$deviceObj->ramp->speed = $urcDevice->ramp_speed;

				$deviceObj->attr = new stdClass;
				$deviceObj->attr->auto_cr = $urcDevice->auto_cr;
				$deviceObj->attr->con_time = $urcDevice->con_time;
				$deviceObj->attr->delay_after_send = $urcDevice->delay_after_send;
			}
		}

		$pageIdx = 0;
		$pageObj = null;
		$curPageId = -2;//-1 is used in db.
		foreach($urcBtns as $btn) {
			
			if($btn->page_id != $curPageId) {

				$deviceObj->pages[$pageIdx] = new stdClass;
				$pageObj = &$deviceObj->pages[$pageIdx];
				$pageIdx++;

				$pageObj->id = $btn->page_id;
				$pageObj->btns = array();
				
				$curPageId = $btn->page_id;
			}

			if($btn->page_hidden) {
				
				if(!isset($pageObj->page_hidden)) {
					$pageObj->page_hidden = 1;
				}
			}
			else {
				
				if(isset($pageObj->page_hidden)) {
					$pageObj->page_hidden = 0;
				}
			}
			
			unset($btn->page_id);
			unset($btn->page_hidden);			
			$pageObj->btns[] = $btn;
		}

		//ErrorDebug::write('getDevice');
		//ErrorDebug::write(json_encode($deviceObj));

		return $deviceObj;		
	}

	public function getMatchObject(&$arItem, $id) {

		foreach($arItem as $item) {
			if($item->id == $id) {
				return $item;
			}
		}

		return null;
	}

	public function checkButtonsMatch(&$urcBtns, &$device, &$new_page_id, &$arDelBtn, &$arUpdateBtn, &$arNewBtn, &$arDelDev) {
		
		$new_page_id = 0;
		
		$chkArr = array();
		foreach($urcBtns as $btn) {			
			$chkArr[$btn->id] = 1;
		}

		foreach($device->pages as $page) {

			$appliedId = $new_page_id;
			if($page->id == -1) {//Hard Buttons
				$appliedId = -1;
			}
			else {
				$new_page_id++;			
			}

			$pageHidden = 0;
			if(isset($page->hidden)) {
				$pageHidden = $page->hidden;
			}

			foreach($page->btns as $btn) {

				$btn->page_id = $appliedId;
				$btn->page_hidden = $pageHidden;

				if(!isset($btn->hidden)) {					
					$btn->hidden = 0;
				}
					
				if(!isset($chkArr[$btn->id])) {
					$arNewBtn[] = $btn;
				}
				else if($chkArr[$btn->id] == -1) {
					return false;
				}
				else if($chkArr[$btn->id] != 1) {
					$arNewBtn[] = $btn;
				}
				else {
					$arUpdateBtn[] = $btn;
					$chkArr[$btn->id] = -1;
				}
			}
		}

		foreach($chkArr as $key => $value) {
			if($value == 1) {
				$arDelBtn[] = $key;

				$btn = $this->getMatchObject($urcBtns, $key);
				if($btn !== null && $btn->link_id >= 0) {
					
					$arDelDev[] = $btn->link_id;
				}
			}
		}

		return true;
	}

	public function storeDevice($deviceId, $deviceData, $isMain) {
		
		$jsonDeviceData = json_encode($deviceData);

		//ErrorDebug::write('storeDevice');
		//ErrorDebug::write($jsonDeviceData);
		
		$device = json_decode($jsonDeviceData);
		
		$urcBtns = DB::table('a_btns')->where('device_id', '=', $deviceId)-> 
			where('room_id', '=', $this->roomId)->orderBy('page_id', 'asc')->get();
			
		$new_page_id = 0;
		$arDelBtn = array();
		$arUpdateBtn = array();
		$arNewBtn = array();
		$arDelDev = array();
		if($this->checkButtonsMatch($urcBtns, $device, $new_page_id, $arDelBtn, $arUpdateBtn, $arNewBtn, $arDelDev) === false) {
			return false;
		}

		if($isMain) {
			if(count($arNewBtn) > 0)
				return false;
		} 
		else {
			if(count($arDelDev) > 0)
				return false;
		}

		try
		{
			DB::begintransaction();

			//delete
			if(count($arDelBtn) > 0) {

				DB::table('a_btns')->where('device_id', '=', $deviceId)-> 
					where('room_id', '=', $this->roomId)->
					whereIn('id', $arDelBtn)->delete();
			}

			if(count($arDelDev) > 0) {

				//delete buttons in the deleted devices
				DB::table('a_btns')->where('room_id', '=', $this->roomId)->
					whereIn('device_id', $arDelDev)->delete();
				//delete devices						
				DB::table('a_devices')->where('room_id', '=', $this->roomId)->
					whereIn('id', $arDelDev)->delete();
			}

			//update
			foreach($arUpdateBtn as $btn) {

				DB::table('a_btns')->where('device_id', '=', $deviceId)-> 
					where('room_id', '=', $this->roomId)->
					where('id', '=', $btn->id)->
					update(array('page_id' => $btn->page_id, 'page_btn_idx' => $btn->page_btn_idx, 
						'display_text' => $btn->display_text, 'hidden_option' => $btn->hidden_option, 'image_name' => $btn->image_name, 
						'auto_wait' => $btn->auto_wait, 'edit_type' => $btn->edit_type, 'popup' => $btn->popup, 'activity' => $btn->activity, 'macro' => $btn->macro,
						'hidden' => $btn->hidden, 'page_hidden' => $btn->page_hidden));
			}

			//add
			if(count($arNewBtn) > 0) {
				
				$query = array();

				$urcBtn = new URCBtnData($this->roomId, $deviceId);
				$btn_id_start = $urcBtn->getNewBtnId();

				foreach($arNewBtn as $btn) {

					if($btn->page_id < 0) {
						$query[] = $urcBtn->newBtnQueryDetail($btn->id, $btn->page_id, $btn->page_btn_idx, $btn->display_text, $btn->hidden_option, 
							$btn->auto_wait, $btn->edit_type, $btn->popup, $btn->activity, $btn->macro, $btn->hidden, $btn->page_hidden);
					}
					else {
						$query[] = $urcBtn->newBtnQueryDetail($btn_id_start, $btn->page_id, $btn->page_btn_idx, $btn->display_text, $btn->hidden_option, 
							$btn->auto_wait, $btn->edit_type, $btn->popup, $btn->activity, $btn->macro, $btn->hidden, $btn->page_hidden);
						$btn_id_start++;
					}
				}

				DB::table('a_btns')->insert($query);

				//set new btn id
				$urcBtn->setNewBtnId($btn_id_start);
			}

			//apply new page id
			$urcPage = new URCPageData($this->roomId, $deviceId);
			$urcPage->setNewPageId($new_page_id);
			//update new DB
			if($isMain === false) {

				//ConDB
				DB::table('a_con_db')->where('device_id', '=', $deviceId)-> 
					where('room_id', '=', $this->roomId)->delete();

				$query = array();
				foreach($device->dbCon as $func) {
					
					if(!isset($func->custom) || $func->custom !== 1) {
						$query[] = array('id' => (int) $func->id, 'device_id' => $deviceId, 'room_id' => $this->roomId, 
							'name' => $func->name, 'type' => $func->type, 'data' => $func->data, 'custom' => 0);
					}
					else {
						$query[] = array('id' => (int) $func->id, 'device_id' => $deviceId, 'room_id' => $this->roomId, 
							'name' => $func->name, 'type' => $func->type, 'data' => $func->data,
							'custom' => 1, 'repeat_min' => $func->repeat_min, 'repeat_macro' => $func->repeat_macro);
					}
				}

				if(count($query) > 0) {
					DB::table('a_con_db')->insert($query);
				}

				//ErrorDebug::write('aa');
				//Key DB
				DB::table('a_keys_db')->where('device_id', '=', $deviceId)-> 
					where('room_id', '=', $this->roomId)->delete();

				$query = array();
				foreach($device->dbKey as $func) {
					
					if(!isset($func->custom) || $func->custom !== 1) {
						$query[] = array('id' => $func->id, 'device_id' => $deviceId, 'room_id' => $this->roomId, 
							'name' => $func->name, 'type' => $func->type, 'data' => $func->data, 'custom' => 0);
					}
					else {
						$query[] = array('id' => $func->id, 'device_id' => $deviceId, 'room_id' => $this->roomId, 
							'name' => $func->name, 'type' => $func->type, 'data' => $func->data,
							'custom' => 1, 'repeat_min' => $func->repeat_min, 'repeat_macro' => $func->repeat_macro);
					}
				}

				//ErrorDebug::write('aa1');
				

				if(count($query) > 0) {
					DB::table('a_keys_db')->insert($query);
				}

				//remain setting
				$metaPwrOn = -1;
				$metaPwrOff = -1;
				$metaPwrToggle = -1;
				$metaInToggle = -1;
				if(isset($device->meta_pwr_on)) {
					$metaPwrOn = $device->meta_pwr_on;
				}
				if(isset($device->meta_pwr_off)) {
					$metaPwrOff = $device->meta_pwr_off;
				}
				if(isset($device->meta_pwr_toggle)) {
					$metaPwrToggle = $device->meta_pwr_toggle;
				}
				if(isset($device->meta_in_toggle)) {
					$metaInToggle = $device->meta_in_toggle;
				}
				if($device->type == URCValues::DB_TYPE_IP ||
					$device->type == URCValues::DB_TYPE_UDP) {

					DB::table('a_devices')->where('room_id', '=', $this->roomId)->
	 					where('id', '=', $deviceId)->update(array('repeat_min' => $device->repeat->min, 'repeat_macro' => $device->repeat->macro,
	 						'ramp_start' => $device->ramp->start, 'ramp_speed' => $device->ramp->speed, 'con_time' => $device->attr->con_time, 'auto_cr' => $device->attr->auto_cr,
	 						'meta_pwr_on' => $metaPwrOn, 'meta_pwr_off' => $metaPwrOff, 'meta_pwr_toggle' => $metaPwrToggle, 'meta_in_toggle' => $metaInToggle));
				}
				else {
	 			
	 				DB::table('a_devices')->where('room_id', '=', $this->roomId)->
	 					where('id', '=', $deviceId)->update(array('repeat_min' => $device->repeat->min, 'repeat_macro' => $device->repeat->macro,
	 						'meta_pwr_on' => $metaPwrOn, 'meta_pwr_off' => $metaPwrOff, 'meta_pwr_toggle' => $metaPwrToggle, 'meta_in_toggle' => $metaInToggle));
	 			}
			}

			DB::commit();
		}
		catch(\Exception $e) 
		{
			DB::rollback();
			return false;
		}

		return true;
	}
}




class URCTwowayDeviceData {

	var $systemData = null;
	var $roomId = -1;

	function __construct(&$system, $roomId) {	
		$this->systemData = $system;
		$this->roomId = $roomId;
	}
	
	public function createDevice($username, $name, $model, $modelId, $categoryId, $target, $isVolCmd, $variables, &$errorInfo) {

		$errorInfo = 'Unable to add this device to your system.';

		//get data
		//extract : repeat{min, macro}, 
		$attr = new stdClass;

		if(!isset($target->port)) {
			$target->port = 0;
		}

		//apply data
		$deviceId = -1;
		try
		{
			DB::begintransaction();

			$deviceId = $this->getNewDeviceId();
			if($deviceId < 0) {
				throw new \Exception('Device ID not created');
			}
			$this->setNewDeviceId($deviceId+1);//DB::table('a_rooms')->where('id', '=', $roomId)->update(array('device_id_start' => $deviceId+1));

			//check already exist
			if($this->isExistDevice($deviceId)) {
				throw new \Exception('Device ID not created');
			}

			$systemId = -1;
			$arTwowayDevices = $this->getTwowayDevicesForSystem($systemId);
			
			if($this->isAddedDevice($model, $modelId, $target, $arTwowayDevices)) {
				throw new \Exception('Already existing device');
			}

			//add
			if($variables == null) {
				$addedModel = array('id' => $deviceId, 'room_id' => $this->roomId, 
					'model' => $model, 'model_id' => $modelId, 'category_id' => $categoryId, 'punch_vol' => -1,				
					'name' => $name, 'target_type' => $target->type, 'target_addr' => $target->addr, 'vol_cmd' => $isVolCmd, 'data' => '', 'extra_info' => '');
			}
			else {
				$addedModel = array('id' => $deviceId, 'room_id' => $this->roomId, 
					'model' => $model, 'model_id' => $modelId, 'category_id' => $categoryId, 'punch_vol' => -1,				
					'name' => $name, 'target_type' => $target->type, 'target_addr' => $target->addr, 'vol_cmd' => $isVolCmd, 'variables' => json_encode($variables), 'data' => '', 'extra_info' => '');
			}

			$addObj = (object) $addedModel;

			//ErrorDebug::write(json_encode($addObj));

			//test max count			
			switch($this->isOverMaxDevices2($systemId, $arTwowayDevices, $addObj))
			{
			case 1:
				{
					$errorInfo = 'Unable to add this device to your system.';
					throw new \Exception($errorInfo);
				}
				break;
			case 2:
			//if($this->isOverMaxDevices($arTwowayDevices)) {
				{
					$errorInfo = 'Unable to add this device to your system.';
					throw new \Exception($errorInfo);
				}
				break;
			case 0:
				break;
			default:
				{
					throw new \Exception('unknown error');
				}
				break;
			}
			
			//add
			DB::table('a_twoway_devices')->insert($addedModel);
			
			/*
			if($variables == null) {
				DB::table('a_twoway_devices')->insert(array('id' => $deviceId, 'room_id' => $this->roomId, 
					'model' => $model, 'model_id' => $modelId, 'punch_vol' => -1,				
					'name' => $name, 'target_type' => $target->type, 'target_addr' => $target->addr, 'data' => '', 'extra_info' => ''));
			}
			else {
				DB::table('a_twoway_devices')->insert(array('id' => $deviceId, 'room_id' => $this->roomId, 
					'model' => $model, 'model_id' => $modelId, 'punch_vol' => -1,				
					'name' => $name, 'target_type' => $target->type, 'target_addr' => $target->addr, 'variables' => json_encode($variables), 'data' => '', 'extra_info' => ''));
			}
			*/

			DB::commit();
		}
		catch(\Exception $e) 
		{
			DB::rollback();
			$deviceId = -1;		
		}

		return $deviceId;
	}

	public function destroyDevice($deviceId) {

		$device = DB::table('a_twoway_devices')->where('room_id', '=', $this->roomId)->
				where('id', '=', $deviceId)->first();

		if($device) {
			try
			{
				DB::begintransaction();

				//delete device 
				DB::table('a_twoway_devices')->where('room_id', '=', $this->roomId)->
					where('id', '=', $deviceId)->delete();
				
				DB::commit();
			}
			catch(\Exception $e) 
			{
				DB::rollback();
				return false;		
			}
		}

		return true;
	}

	public function editDevice($deviceId, $deviceName, $target, $variables) {

		$device = DB::table('a_twoway_devices')->where('room_id', '=', $this->roomId)->
				where('id', '=', $deviceId)->first();

		if($device) {
			try
			{
				DB::begintransaction();

				//con_time is not set, it is now showed in User side
				if($variables == null) {
					$updatedRow = DB::table('a_twoway_devices')->where('room_id', '=', $this->roomId)->
						where('id', '=', $deviceId)->update(
							array('name' => $deviceName, 'target_type' => $target->type, 'target_addr' => $target->addr));
				}
				else {
					$updatedRow = DB::table('a_twoway_devices')->where('room_id', '=', $this->roomId)->
						where('id', '=', $deviceId)->update(
							array('name' => $deviceName, 'target_type' => $target->type, 'target_addr' => $target->addr, 'variables' => json_encode($variables)));
				}

				DB::commit();
			}
			catch(\Exception $e) 
			{
				DB::rollback();
				return false;
			}
		}

		return true;
	}

	public function updateDevice($deviceId, $data, &$updatedRow) {

		$jsonData = json_encode($data);
		try
		{
			DB::begintransaction();

			//con_time is not set, it is now showed in User side
			$updatedRow = DB::table('a_twoway_devices')->where('room_id', '=', $this->roomId)->
				where('id', '=', $deviceId)->update(array('data' => $jsonData));
			
			DB::commit();
		}
		catch(\Exception $e) 
		{
			DB::rollback();
			return false;
		}
		
		return true;
	}

	public function getPunchDevice($deviceId) {

		$device = DB::table('a_twoway_devices')->where('room_id', '=', $this->roomId)->
				where('id', '=', $deviceId)->first();	

		if(!$device)
			return -1;

		return $device->punch_vol;
	}

	public function setPunchDevice($deviceFrom, $deviceTo) {

		$updatedRow = DB::table('a_twoway_devices')->where('room_id', '=', $this->roomId)->
				where('id', '=', $deviceTo)->update(array('punch_vol' => (int)$deviceFrom));		

		//if($updatedRow <= 0)
		//	return false;

		return true;
	}

	public function setPunchDevices($deviceFrom, $deviceTo) {

		$jsonData = json_encode($deviceTo);
		$devices = json_decode($jsonData);

		if(!is_array($devices)) {
			return false;
		}

		try
		{
			DB::begintransaction();

			foreach($devices as $item) {

				DB::table('a_twoway_devices')->where('room_id', '=', $this->roomId)->
					where('id', '=', $item)->update(array('punch_vol' => (int)$deviceFrom));
			}

			DB::commit();
		}
		catch(\Exception $e) 
		{
			DB::rollback();
			return false;
		}
		
		return true;
	}

	public function getExtraInfo($deviceId) {

		$device = DB::table('a_twoway_devices')->where('room_id', '=', $this->roomId)->
				where('id', '=', $deviceId)->first();	

		if(!$device)
			return false;

		return json_decode($device->extra_info);
	}

	public function setExtraInfo($deviceId, $data) {

		$updatedRow = DB::table('a_twoway_devices')->where('room_id', '=', $this->roomId)->
				where('id', '=', $deviceId)->update(array('extra_info' => $data));

		//if($updatedRow <= 0)
		//	return false;

		return true;
	}

	protected function getNewDeviceId() {

		$system = DB::table('a_systems')->where('id', '=', $this->systemData->id)->first();
		if(!$system) {
			return -1;
		}

		return $system->twoway_device_id_start;
	}

	public function setNewDeviceId($newDeviceId) {
		
		DB::table('a_systems')->where('id', '=', $this->systemData->id)->update(array('twoway_device_id_start' => $newDeviceId));
	}

	protected function isExistDevice($deviceId) {

		$existDB = DB::table('a_twoway_devices')->where('id', '=', $deviceId)->
			where('room_id', '=', $this->roomId)->first(); 
		if($existDB) {
			return 1;
		}
		return 0;
	}

	protected function &getTwowayDevicesForSystem(&$systemId) {

		$systemId = -1;
		$room = DB::table('a_rooms')->where('id', '=', $this->roomId)->first();
		if($room) {

			$systemId = $room->system_id;

			$roomIds = array();
			$rooms = DB::table('a_rooms')->where('system_id', '=', $systemId)->get();
			foreach($rooms as $roomItem) {
				$roomIds[] = $roomItem->id;
			}	

			$existDB = DB::table('a_twoway_devices')->whereIn('room_id', $roomIds)->get(); 
			if($existDB && count($existDB) > 0) {
				return $existDB;
			}
		}

		$existDB = array();
		return $existDB;
	}

	protected function isAddedDevice($model, $modelId, $target, &$arTwowayDevs) {

		if($model == 'TRF-ZW1') {
			
			if($arTwowayDevs != null) {

				foreach($arTwowayDevs as $twowayDev) {
					if($twowayDev->model == $model)
						return 1;
				}
			}
		}

		switch($target->type & 0xffff)
		{
		case URCValues::TWOWAY_TYPE_MAC:
		case URCValues::TWOWAY_TYPE_IP:
			$existDB = DB::table('a_twoway_devices')->where('target_addr', '=', $target->addr)->
				where('room_id', '=', $this->roomId)->first(); 
			if($existDB) {
				return 1;
			}
			break;
		case URCValues::TWOWAY_TYPE_SERVICE:
			$existDB = DB::table('a_twoway_devices')->where('model', '=', $model)->where('model_id', '=', $modelId)->
				where('room_id', '=', $this->roomId)->first(); 
			if($existDB) {
				return 1;
			}
			break;
		default:
			break;
		}

		return 0;
	}

	protected function isOverMaxDevices(&$arTwowayDevs) {

		if($arTwowayDevs != null && count($arTwowayDevs) >= URCValues::MAX_TWOWAY_MODULE_CNT) {
			return 1;
		}
			
		return 0;
	}

	protected function isSameDevice(&$dev1, &$dev2) {

		if($dev1->model_id !== $dev2->model_id) {
			return false;
		}
		
		$len1 = 0;
		if(isset($dev1->variables)) {
			$len1 = strlen($dev1->variables);
		}
		$len2 = 0;
		if(isset($dev2->variables)) {
			$len2 = strlen($dev2->variables);
		}
		if($len1 != $len2) {
			return false;
		}
		if($len1 > 0) {
			if(strcasecmp($dev1->variables, $dev2->variables)) {
				return false;
			}
		}
				 
		switch($dev1->target_type)
		{
		case URCValues::TWOWAY_TYPE_MAC:
			if(strcasecmp($dev1->target_addr, $dev2->target_addr) == 0) {
				return true;
			}
			break;					
		case URCValues::TWOWAY_TYPE_IP:
			if(strcasecmp($dev1->target_addr, $dev2->target_addr) == 0) {
				return true;
			}
			break;	
		default:
			return true;
			break;
		}

		return false;
	}

	protected function isOverMaxDevices2($systemId, &$arTwowayDevs, &$addedModel) {

		//ErrorDebug::write(json_encode($addedModel));

		$bstation = DB::table('a_bstations')->where('system_id', '=', $systemId)->
			where('master', '=', 1)->first();

		$maxCnt = URCValues::MAX_TWOWAY_MODULE_CNT;
		$maxSameCnt = URCValues::MAX_SAME_TWOWAY_MODULE_CNT;
		if($bstation) {
			URCValues::getMaxTwowayLimit($bstation->type, $maxCnt, $maxSameCnt);
		}

		$isTRFZW = false;
		$sameDeviceCnt = 0;
		$realDevices = array();
		$bAlreadyExist = false;
		foreach($arTwowayDevs as $tDevice) {

			$bfound = false;
			foreach($realDevices as $realDevice) {

				if(!$this->isSameDevice($tDevice, $realDevice)) {
					continue;
				}
				$bfound = true;
				break;
			}

			if(!$bfound) {
				$realDevices[] = $tDevice;

				if($tDevice->model_id === $addedModel->model_id) {
					$sameDeviceCnt++;
				}

				if($this->isSameDevice($tDevice, $addedModel)) {
					$bAlreadyExist = true;
				}

				if($tDevice->model == "TRF-ZW1") {
					$isTRFZW = true;
				}
			}

		}

		//ErrorDebug::write(count($realDevices));
		//ErrorDebug::write($sameDeviceCnt);
		//ErrorDebug::write($bAlreadyExist);

		if($bAlreadyExist) {
			return 0;
		}

		//$maxCnt = URCValues::MAX_TWOWAY_MODULE_CNT;
		if(!$isTRFZW) {
			$maxCnt--;
		}
		if(count($realDevices) >= $maxCnt) {
			return 1;
		}
		if($sameDeviceCnt >= $maxSameCnt) {
			return 2;
		}

		return 0;
	}

	public function getDevice($deviceId) {

		$urcDevice = DB::table('a_twoway_devices')->where('room_id', '=', $this->roomId)->
			where('id', '=', $deviceId)->first(); 
		if(!$urcDevice) {
			return false;
		}

		return $urcDevice;		
	}
	
	public function getMacroButtonsFromDevice() {

		$urcDevices = DB::table('a_twoway_devices')->where('room_id', '=', $this->roomId)->
			select('id', 'model_id', 'category_id', 'model', 'name', 'auto_wait', 'edit_type', 'popup', 'activity', 'macro')->get();

		return $urcDevices;
	}

	public function getMacroFromDevice($deviceId) {

		$urcDevice = DB::table('a_twoway_devices')->where('room_id', '=', $this->roomId)->
			where('id', '=', $deviceId)->first(); 

		if(!$urcDevice) {
			return false;
		}

		$activity = json_decode($urcDevice->activity);
		$macro = json_decode($urcDevice->macro);

		return array('auto_wait' => $urcDevice->auto_wait, 'edit_type' => $urcDevice->edit_type, 'popup' => $urcDevice->popup,
			'activity' => $activity, 'macro' => $macro);
	}

	public function delMacroFromDevice($deviceId) {

		$urcDevice = DB::table('a_twoway_devices')->where('room_id', '=', $this->roomId)->
			where('id', '=', $deviceId)->update(array('auto_wait' => 1, 'edit_type' => URCValues::ETYPE_MACRO, 'popup' => 0, 'activity' => '', 'macro' => '')); 

		return true;
	}

	public function storeMacroFromDevice($deviceId, $auto_wait, $editType, $popup, $activity, $macro) {
		
		$jsonActivity = json_encode($activity);

		if($editType == URCValues::ETYPE_ACTIVITY) {
			
			//ErrorDebug::write('jsonActivity:'.$jsonActivity);
			//ErrorDebug::write('jsonMacro:'.$jsonMacro);

			$urcDevice = DB::table('a_twoway_devices')->where('room_id', '=', $this->roomId)->
				where('id', '=', $deviceId)->update(array('auto_wait' => $auto_wait, 'edit_type' => $editType, 'popup' => $popup, 'activity' => $jsonActivity, 'macro' => ''));//$jsonMacro)); 

			return true;
		}
		
		if($editType == URCValues::ETYPE_MACRO){
		
			$jsonMacro = json_encode($macro);

			$urcDevice = DB::table('a_twoway_devices')->where('room_id', '=', $this->roomId)->
				where('id', '=', $deviceId)->update(array('auto_wait' => $auto_wait, 'edit_type' => $editType, 'popup' => $popup, 'activity' => $jsonActivity, 'macro' => $jsonMacro)); 

			return true;
		}
		
		return false;
	}
}


class URCScheEventData {

	var $systemId = -1;
	var $roomId = -1;

	function __construct($systemId, $roomId) {	
		$this->systemId = $systemId;
		$this->roomId = $roomId;
	}


	protected function getNewEventId() {
		
		$room = DB::table('a_rooms')->where('id', '=', $this->roomId)->first();
		if(!$room) {
			return -1;
		}


		//ErrorDebug::write('getnew event id');
		//ErrorDebug::write($room->event_id_start);

		return $room->event_id_start;
	}

	public function setNewEventId($newEventId) {

		//ErrorDebug::write('setnew event id');
		//ErrorDebug::write($newEventId);

		DB::table('a_rooms')->where('id', '=', $this->roomId)->update(array('event_id_start' => $newEventId));
	}

	protected function isExistEvent($eventId) {

		$existDB = DB::table('a_events')->where('id', '=', $eventId)->
			where('room_id', '=', $this->roomId)->first(); 
		if($existDB) {
			return 1;
		}
		return 0;
	}

	public function getEvents() {

		$chkExisting = DB::table('a_events')->where('room_id', '=', $this->roomId)->
			orderBy('order', 'asc')->get();
		foreach($chkExisting as $roomChk) {

			unset($chkExisting->room_id);
			unset($chkExisting->order);
		}

		return $chkExisting;
	}

	public function storeEvents(&$data) {

		$jsonData = json_encode($data);

		//ErrorDebug::write('storeEvents');
		//ErrorDebug::write($jsonData);
		
		$events = json_decode($jsonData);

		$count = count($events);
		if($count <= 0) {
			return true;
		}

		try
		{
			DB::begintransaction();

			$idx = 0;
			foreach($events as $item) {

				$hidden = 0;
				if(isset($item->hidden)) {
					$hidden = $item->hidden;
				}
				DB::table('a_events')->where('room_id', '=', $this->roomId)->
					where('id', '=', $item->id)->update(array('image_name' => $item->image_name,
					'display_text' => $item->display_text, 'hidden_option' => $item->hidden_option,
					'macro' => $item->macro, 'hidden' => $hidden, 'default_state' => $item->default_state, 
					'option' => $item->option, 'day_week' => $item->day_week, 'time' => $item->time, 'order' => $idx));

				$idx++;
			}

			DB::commit();
		}
		catch(\Exception $e) 
		{
			DB::rollback();
			return false;
		}

		return true;
	}

	public function getEvent($id) {
		
		$chkExisting = DB::table('a_events')->where('room_id', '=', $this->roomId)->
			where('id', '=', $id)->first();

		if($chkExisting) {

			unset($chkExisting->room_id);
			return $chkExisting;

		}

		return false;
	}

	public function delEvent($id) {

		$chkExisting = DB::table('a_events')->where('room_id', '=', $this->roomId)->
			where('id', '=', $id)->delete();

		return true;
	}

	public function createEvent($text, $imageName, $macro, $defaultState, $option, $dayWeek, $time) {

		$jsonMacro = json_encode($macro);

		$eventId = $this->getNewEventId();
		if($eventId < 0)
			return -1;
		//check already exist
		if($this->isExistEvent($eventId))
			return -1;

		try
		{
			DB::begintransaction();
			
			$this->setNewEventId($eventId+1);

			DB::table('a_events')->insert(array('id' => $eventId, 'room_id' => $this->roomId, 'image_name' => $imageName, 'display_text' => $text, 
				'macro' => $jsonMacro, 'default_state' => $defaultState, 
				'option' => $option, 'day_week' => $dayWeek, 'time' => $time, 'order' => $eventId));
			
			DB::commit();
		}
		catch(\Exception $e) 
		{
			DB::rollback();
			return -1;
		}

		return $eventId;
	}

	public function setEvent($id, $text, $imageName, $macro, $defaultState, $option, $dayWeek, $time) {

		$jsonMacro = json_encode($macro);

		DB::table('a_events')->where('room_id', '=', $this->roomId)->
			where('id', '=', $id)->
			update(array('image_name' => $imageName, 'display_text' => $text, 
			'macro' => $jsonMacro, 'default_state' => $defaultState, 
			'option' => $option, 'day_week' => $dayWeek, 'time' => $time));
		
		return true;
	}

	public function updateEventTime($id, $dayWeek, $time) {

		DB::table('a_events')->where('room_id', '=', $this->roomId)->
			where('id', '=', $id)->
			update(array('day_week' => $dayWeek, 'time' => $time));
		
		return true;
	}

	public function setEventStatus($id, $defaultState) {
		
		DB::table('a_events')->where('room_id', '=', $this->roomId)->
			where('id', '=', $id)->
			update(array('default_state' => $defaultState));
		
		return true;
	}
}


class URCRoomData {

	var $systemId = -1;

	function __construct($systemId) {	
		$this->systemId = $systemId;
	}

	public function isOverRoomCount() {
		
		$rooms = DB::table('a_rooms')->where('system_id', '=', $this->systemId)->get();
		if(count($rooms) >= URCValues::MAX_ROOM_CNT)
			return true;

		return false;
	}

	//return : new room id
	public function createRoom($bstationType, $bstationName, $bstationMac, $roomName, $table_hdr){

		$roomId = -1;
		try
		{
			DB::begintransaction();

			$roomId = $this->newRoom(0, $bstationType, $bstationName, $bstationMac, $roomName);
			if($roomId < 0) {
				throw new \Exception('Room ID not created');
			}
			
			$urcDev = new URCDeviceData($roomId);
			$deviceId = $urcDev->newMainDevice();
			if($deviceId < 0) {
				throw new \Exception('Device ID not created');
			}

			//set Main Device ID
			if($this->setMainDeviceId($roomId, $deviceId) == false) {
				throw new \Exception('fail to set the Main device id');
			}
			
			//system button
			$urcBtn = new URCBtnData($roomId, -1);
			$urcBtn->newSystemOffBtn();

			DB::commit();
		}
		catch(\Exception $e) 
		{
			DB::rollback();
			$roomId = -1;				
		}

		return $roomId;
	}

	public function destroyRoom($roomId) {

		try
		{
			DB::begintransaction();

			$this->deleteRoom($roomId);
			
			DB::table('a_rooms')->where('system_id', '=', $this->systemId)->
				where('id', '=', $roomId)->delete();

			DB::table('a_download')->where('system_id', '=', $this->systemId)->
				where('id', '=', $roomId)->delete();

			DB::commit();
		}
		catch(\Exception $e) 
		{
			DB::rollback();
			return false;				
		}

		return true;
	}
	
	public function editRoom($roomId, $name) {
	
		$updatedRow = DB::table('a_rooms')->where('system_id', '=', $this->systemId)->
			where('id', '=', $roomId)->update(array('name' => $name));
		
		if($updatedRow <= 0)
			return false;
		
		return true;
	}

	public function getRoom($roomId) {
		
		$room = DB::table('a_rooms')->where('system_id', '=', $this->systemId)->
			where('id', '=', $roomId)->first();
		if(!$room)
			return false;
		
		$roomObj = new stdClass;

		$roomObj->name = $room->name;
		$roomObj->id = $room->id;
		//$roomObj->bstation = $room->bstation;

		//remotes
		$roomObj->remotes = array();

		$remotes = DB::table('a_remotes')->where('room_id', '=', $room->id)->get();

		$lenRemote = 0;
		if($remotes) $lenRemote = count($remotes);

		for($i2 = 0; $i2 < $lenRemote; $i2++) {

			$roomObj->remotes[$i2] = $remotes[$i2];
			unset($roomObj->remotes[$i2]->room_id);
		}

		//bstations
		$roomObj->bstations = array();

		$bstations = DB::table('a_bstations')->where('room_id', '=', $room->id)->get();

		$lenBStation = 0;
		if($bstations) $lenBStation = count($bstations);

		for($i2 = 0; $i2 < $lenBStation; $i2++) {

			$roomObj->bstations[$i2] = $bstations[$i2];
			unset($roomObj->bstations[$i2]->room_id);
			unset($roomObj->bstations[$i2]->system_id);
		}

		//schedule event
		$roomObj->scheEvent = array();
		$events = DB::table('a_events')->where('room_id', '=', $room->id)->
			orderBy('order', 'asc')->get();
		$lenEvent = 0;
		if($events) $lenEvent = count($events);

		for($i2 = 0; $i2 < $lenEvent; $i2++) {

			$roomObj->scheEvent[$i2] = $events[$i2];
			unset($roomObj->scheEvent[$i2]->room_id);
		}


		//devices		
		$roomObj->devices = array();

		$devices = DB::table('a_devices')->where('room_id', '=', $room->id)->
			whereNotIn('id', array($room->main_device_id))->get();//not needed system(please delete system_id in the a_devices)

		$urcDev = new URCDeviceData($roomId);

		$lenDev = 0;
		if($devices) $lenDev = count($devices);
		for($i2 = 0; $i2 < $lenDev; $i2++) {

			//$roomObj->devices[$i2] = new stdClass;

			$devices[$i2]->exist_vol = URCDeviceData::isExistVol($devices[$i2]);

			$roomObj->devices[$i2] = $devices[$i2];
			unset($roomObj->devices[$i2]->room_id);
			unset($roomObj->devices[$i2]->page_id_start);
			unset($roomObj->devices[$i2]->btn_id_start);

			$urcConDB = $urcDev->getConDevData($roomObj->devices[$i2]->id);
			foreach($urcConDB as $func) {
				//unset($func->data);
				unset($func->device_id);
				unset($func->room_id);
				
				if($func->custom !== 1) {
					unset($func->press_hold);
					unset($func->repeat_min);
					unset($func->repeat_macro);
				}
				unset($func->custom);
			}

			$roomObj->devices[$i2]->funcs = $urcConDB;
		}

		//twoway_devices
		$roomObj->twoway_devices = array();

		$twoway_devices = DB::table('a_twoway_devices')->where('room_id', '=', $room->id)->get();

		$lenDev = 0;
		if($devices) $lenDev = count($twoway_devices);
		for($i2 = 0; $i2 < $lenDev; $i2++) {

			$varDecode = json_decode($twoway_devices[$i2]->variables);
			$twoway_devices[$i2]->variables = $varDecode;

			$dataDecode = json_decode($twoway_devices[$i2]->data);
			$twoway_devices[$i2]->data = $dataDecode;

			$extraDecode = json_decode($twoway_devices[$i2]->extra_info);
			$twoway_devices[$i2]->extra_info = $extraDecode;

			$roomObj->twoway_devices[$i2] = $twoway_devices[$i2];
			unset($roomObj->twoway_devices[$i2]->room_id);

			unset($roomObj->twoway_devices[$i2]->auto_wait);
			unset($roomObj->twoway_devices[$i2]->edit_type);
			unset($roomObj->twoway_devices[$i2]->popup);
			unset($roomObj->twoway_devices[$i2]->activity);
			unset($roomObj->twoway_devices[$i2]->macro);
		}

		//amazon echo
		$amazonObj = new URCAmazonData($this->systemId);
		$amazonService = $amazonObj->getServiceObj();
		if($amazonService) {
			$roomObj->amazon_echo = new stdClass;
			$roomObj->amazon_echo->scenes = $amazonObj->getScenes($room->id);
			$roomObj->amazon_echo->link_code = $amazonService->link_code;
		}
		
		return $roomObj;
	}

	public function setRemote($roomId, $mac, $type, $name) {
		
		$chkExisting = DB::table('a_remotes')->where('room_id', '=', $roomId)->
			where('system_id', '=', $this->systemId)->first();
		if($chkExisting) {
			$updatedRow = DB::table('a_remotes')->where('id', '=', $chkExisting->id)->update(array('mac' => $mac, 'type' => $type, 'name' => $name));
		}
		else {
			DB::table('a_remotes')->insert(array('system_id' => $this->systemId, 'room_id' => $roomId, 'mac' => $mac, 'type' => $type, 'name' => $name));
		}
		
		return true;
	}

	public function addRemote($roomId, $mac, $type, $name) {
		
		DB::table('a_remotes')->insert(array('system_id' => $this->systemId, 'room_id' => $roomId, 'mac' => $mac, 'type' => $type, 'name' => $name));		

		return true;
	}

	public function delRemote($roomId, $mac) {
		
		DB::table('a_remotes')->where('room_id', '=', $roomId)->where('system_id', '=', $this->systemId)->
			where('mac', '=', $mac)->delete();	

		return true;
	}

	public function applyRemoteMac($roomId, $id, $type, $mac) {
		
		DB::table('a_remotes')->where('room_id', '=', $roomId)->
			where('system_id', '=', $this->systemId)->
			where('id', '=', $id)->where('type', '=', $type)->update(array('mac' => $mac));
		
		return true;
	}

	public function setBStation($roomId, $orgMac, $newModelType, $newMac) {

		DB::table('a_devices')->where('room_id', '=', $roomId)->
			where('target_addr', '=', $orgMac)->update(array('target_addr' => $newMac));

		$updatedRow = DB::table('a_bstations')->where('system_id', '=', $this->systemId)->
			where('mac', '=', $orgMac)->
			update(array('mac' => $newMac, 'type' => $newModelType));

		//DB::table('a_devices')->where('target_addr', '=', $orgMac)->update();

		return true;
	}

	public function addBStation($roomId, $mac, $type, $name, $lightLevel) {

		DB::table('a_bstations')->insert(array('system_id' => $this->systemId, 'room_id' => $roomId,
		 'mac' => $mac, 'type' => $type, 'name' => $name, 'light_level' => $lightLevel));

		return true;
	}

	public function editBStation($roomId, $mac, $type, $name, $lightLevel) {

		DB::table('a_bstations')->where('system_id', '=', $this->systemId)->
			where('room_id', '=', $roomId)->
			where('mac', '=', $mac)->update(array('type' => $type, 'name' => $name, 'light_level' => $lightLevel));

		return true;
	}

	public function delBStation($roomId, $mac) {

		DB::table('a_bstations')->where('system_id', '=', $this->systemId)-> 
			where('room_id', '=', $roomId)->
			where('mac', '=', $mac)->delete();

		return true;
	}

	public function applyBStationMac($roomId, $id, $type, $mac) {

		$bstationOrg = DB::table('a_bstations')->where('system_id', '=', $this->systemId)->
			where('room_id', '=', $roomId)->
			where('id', '=', $id)->first();
		if(!$bstationOrg) {
			return false;
		}

		try
		{		
			DB::begintransaction();

			//apply bstation
			DB::table('a_bstations')->where('system_id', '=', $this->systemId)->
				where('room_id', '=', $roomId)->
				where('id', '=', $id)->where('type', '=', $type)->update(array('mac' => $mac));

			//change device info
			DB::table('a_devices')->where('room_id', '=', $roomId)->
				where('target_addr', '=', $bstationOrg->mac)->update(array('target_addr' => $mac));
			
			DB::commit();
		}
		catch(\Exception $e) 
		{
			DB::rollback();
			return false;				
		}

		return true;
	}

	public function getDevices($roomId) {

		$devices = DB::table('a_devices')->where('room_id', '=', $roomId)->get();
		if(!$devices)
			return false;
		
		return json_encode($devices);
	}


	public function getConDevs($roomId) {
		$condevs = DB::table('a_con_db')->where('room_id', '=', $roomId)->get();
		if(!$condevs)
			return false;
		
		return json_encode($condevs);
	}

	public function newRoom($master, $bstationType, $bstationName, $bstationMac, $roomName) {

		$roomId = DB::table('a_rooms')->insertGetId(array('system_id' => $this->systemId, 'device_id_start' => 0, 
				'name' => $roomName));

		if($roomId >= 0) {
			$bstationId = DB::table('a_bstations')->insert(array('system_id' => $this->systemId, 'room_id' => $roomId,
				'mac' => $bstationMac, 'type' => $bstationType, 'name' => $bstationName, 'master' => $master));
		}

		return $roomId;
	}

	public function setMainDeviceId($roomId, $mainDeviceId) {

		$updateRow = DB::table('a_rooms')->where('system_id', '=', $this->systemId)->
			where('id', '=', $roomId)->update(array('main_device_id' => $mainDeviceId));
		
		if($updateRow <= 0)
			return false;

		return true;
	}

	public function deleteRoom($roomId) {

		DB::table('a_devices')->where('room_id', '=', $roomId)->delete();
		DB::table('a_keys_db')->where('room_id', '=', $roomId)->delete();
		DB::table('a_con_db')->where('room_id', '=', $roomId)->delete();
		//DB::table('a_pages')->where('room_id', '=', $roomId)->delete();
		DB::table('a_btns')->where('room_id', '=', $roomId)->delete();

		DB::table('a_remotes')->where('room_id', '=', $roomId)->delete();
		DB::table('a_bstations')->where('room_id', '=', $roomId)->delete();

		DB::table('a_twoway_devices')->where('room_id', '=', $roomId)->delete();

		DB::table('a_events')->where('room_id', '=', $roomId)->delete();

		DB::table('a_amazon_scene')->where('room_id', '=', $roomId)->delete();
	}
}

class URCSystemData {

	var $userId = -1;

	function __construct($userId) {	
		$this->userId = $userId;
	}

	public static function parseUserInfo($userInfo, &$username, &$password) {

		$userDecoded = base64_decode($userInfo);
		$pos = strpos($userDecoded, ':');
		if($pos <= 3) {//username
			return false;
		}

		$username = substr($userDecoded, 0, $pos);
		$password = substr($userDecoded, $pos+1);

		if(strlen($password) < 3) { //password
			return false;
		}

		return true;
	}

	public static function getUserObject($userInfo) {

		$username = '';
		$password = '';
		if(URCSystemData::parseUserInfo($userInfo, $username, $password) === false) {
			return false;
		}

		$editor_type = Config::get('editorenv.editor_type');
		$user = User::where('username', '=', $username)->where('editor', '=', $editor_type)->first();
		if(!$user) {
			return false;
		}

		if($password !== Crypt::decrypt($user->password)) {
			return false;
		}

		return $user;
	}



	public static function isValidSystem($userId, $systemId) {
		
		$system = DB::table('a_systems')->where('id', '=', $systemId)->
			where('user_id', '=', $userId)->first();
		
		if(!$system) {
			return false;
		}

		return $system;
	}

	public static function isValidRoom($userId, $roomId) {
		
		$room = DB::table('a_rooms')->where('id', '=', $roomId)->first();
		if(!$room) {
			return false;
		}

		$system = DB::table('a_systems')->where('id', '=', $room->system_id)->
			where('user_id', '=', $userId)->first();
		
		if(!$system) {
			return false;
		}

		return true;
	}

	public static function isValidRoom2($userId, $roomId, &$system, &$room) {
		
		$room = DB::table('a_rooms')->where('id', '=', $roomId)->first();
		if(!$room) {
			return false;
		}

		$system = DB::table('a_systems')->where('id', '=', $room->system_id)->
			where('user_id', '=', $userId)->first();
		
		if(!$system) {
			return false;
		}

		return true;
	}

	public static function isValidSystemForDealer($dealerGrpId, $systemId) {

		$system = DB::table('a_systems')->where('id', '=', $systemId)->first();

		if(!$system) {
			return false;
		}

		if($system->dealer_grp_id !== $dealerGrpId) {
			return false;
		}

		return $system;
	}

	public static function isValidRoomForDealer($dealerGrpId, $roomId) {
		
		$room = DB::table('a_rooms')->where('id', '=', $roomId)->first();
		if(!$room) {
			return false;
		}
		
		$system = DB::table('a_systems')->where('id', '=', $room->system_id)->
			where('dealer_grp_id', '=', $dealerGrpId)->first();
		
		if(!$system) {
			return false;
		}
		
		return true;
	}

	public static function isValidRoomForDealer2($dealerGrpId, $roomId, &$system, &$room) {

		$room = DB::table('a_rooms')->where('id', '=', $roomId)->first();
		if(!$room) {
			return false;
		}

		$system = DB::table('a_systems')->where('id', '=', $room->system_id)->
			where('dealer_grp_id', '=', $dealerGrpId)->first();
		
		if(!$system) {
			return false;
		}

		/*
		$system = DB::table('a_systems')->where('id', '=', $room->system_id)->first();
		
		if(!$system) {
			return false;
		}

		if($system->dealer_grp_id !== $dealerGrpId) {
			return false;
		}
		*/

		return $system;
	}

	public static function updateEditTime($systemId, $updater) {
		
		DB::table('a_systems')->where('id', '=', $systemId)->
			update(array('updated_at' => date('Y-m-d H:i:s')));
	}

	public static function updateEditTimeFromRoom($roomId, $updater) {

		$room = DB::table('a_rooms')->where('id', '=', $roomId)->first();
		if(!$room) {
			return;
		}

		URCSystemData::updateEditTime($room->system_id, $updater);
	}
	
	public function getSystems() {
		
		return DB::table('a_systems')->where('user_id', '=', $this->userId)->
			select('id', 'controller_id', 'name', 'timezone_id', 'timezone_dst', 'time_type',
				'home_btn_option', 'dealer_id')->get();
	}

	public function calcJobDone($systemId) {

		//remotes
		$remotes = DB::table('a_remotes')->where('system_id', '=', $systemId)->get();
		foreach($remotes as $remote) {

			if(strncmp($remote->mac, 'TMP_', 4) == 0) {
				return false;
			}
		}

		//bstations
		$bstations = DB::table('a_bstations')->where('system_id', '=', $systemId)->get();
		foreach($bstations as $bstation) {

			if(strncmp($bstation->mac, 'TMP_', 4) == 0) {
				return false;
			}
		}

		//devices
		$rooms = DB::table('a_rooms')->where('system_id', '=', $systemId)->get();
		foreach($rooms as $room) {

			$devices = DB::table('a_devices')->where('room_id', '=', $room->id)->
				whereNotIn('id', array($room->main_device_id))->get();//not needed system(please delete system_id in the a_devices)

			foreach($devices as $device) {

				if($device->target_type == URCValues::DB_TYPE_IP ||
					$device->target_type == URCValues::DB_TYPE_UDP) {
					if(strlen($device->target_attr) < 1 || strncmp($device->target_attr, 'TMP_', 4) == 0) {
						return false;
					}
				}
				else {					
				}				
			}
		}

		return true;
	}

	public function setJobStatus($systemId, $status) {
		
		$updatedRow = DB::table('a_systems')->where('user_id', '=', $this->userId)->
			where('id', '=', $systemId)->update(array('job_done' => $status));

		return true;
	}
	
	public function setTimezone($systemId, $timezoneId, $dst, $timeType) {
		
		$updatedRow = DB::table('a_systems')->where('user_id', '=', $this->userId)->
			where('id', '=', $systemId)->update(array('timezone_id' => $timezoneId, 'timezone_dst' => $dst, 'time_type' => $timeType));

		return true;
	}

	public function deleteBStationFromOther($bstation) {

		$system = DB::table('a_systems')->where('id', '=', $bstation->system_id)->first();

		if($system->user_id == $this->userId) {//already used
			return false;
		}

		try
		{		
			DB::begintransaction();

			//delete bstation
			DB::table('a_bstations')->where('id', '=', $bstation->id)->delete();
					
			if($bstation->master) {
				
				//change system info			
				DB::table('a_systems')->where('id', '=', $system->id)->
					update(array('controller_id' => ''));

				//delete download data
				DB::table('a_download')->where('id', '=', $system->user_id)->
					where('system_id', '=', $system->id)->delete();
			}

			DB::commit();
		}
		catch(\Exception $e) 
		{
			DB::rollback();
			return false;				
		}
		
		return true;
	}

	public function deleteRemoteFromOther($remote) {

		$system = DB::table('a_systems')->where('id', '=', $remote->system_id)->first();

		if($system->user_id == $this->userId) {//already used
			return false;
		}

		try
		{		
			DB::begintransaction();

			//delete remote
			DB::table('a_remotes')->where('id', '=', $remote->id)->delete();

			DB::commit();
		}
		catch(\Exception $e) 
		{
			DB::rollback();
			return false;				
		}
		
		return true;
	}

	public function validSystemMain($systemId, &$errMsg) {

		$system = DB::table('a_systems')->where('id', '=', $systemId)->
			where('user_id', '=', $this->userId)->first();
		if(!$system) {
			return false;
		}

		//rooms
		$rooms = DB::table('a_rooms')->where('system_id', '=', $systemId)->get();
		
		$lenRoom = 0;
		if($rooms) $lenRoom = count($rooms);

		try
		{

			DB::begintransaction();

			for($i = 0; $i < $lenRoom; $i++) {

				//devices
				$mainDev = DB::table('a_devices')->where('room_id', '=', $rooms[$i]->id)->
					where('id', array($rooms[$i]->main_device_id))->first();

				if($mainDev) {
					//DB::table('a_devices')->where('room_id', '=', $rooms[$i]->id)->
					//	where('id', array($rooms[$i]->main_device_id))->delete();
					//ErrorDebug::write('del'.$rooms[$i]->main_device_id);
ErrorDebug::write('=============================');
						
					if($mainDev->btn_id_start == 8192) {
						ErrorDebug::write("ERR".$rooms[$i]->id);
						//$sql = mysql_query(" SELECT MAX(column) `max` FROM tableName WHERE variable='$var' ")						
					}
					else {
						ErrorDebug::write("OK".$rooms[$i]->id);
						ErrorDebug::write("btnID".$mainDev->btn_id_start);
					}

					$btn = DB::table('a_btns')->where('room_id', '=', $rooms[$i]->id)->
							where('device_id', '=', $rooms[$i]->main_device_id)->orderBy('id', 'desc')->first();
					if($btn) {
						ErrorDebug::write($btn->id);
						if($btn->id >= $mainDev->btn_id_start) {
							ErrorDebug::write('OVER'.$btn->id.'st'.$mainDev->btn_id_start);
						}
					}
					else {
						ErrorDebug::write('no btn');
					}					
					
					continue;
				}

				ErrorDebug::write('converted');
				throw new \Exception('Device ID not created');
				
				$roomId = $rooms[$i]->id;

				$urcDev = new URCDeviceData($roomId);
				$mainDevId = $urcDev->repairMainDevice($rooms[$i]->main_device_id);
				if($mainDevId < 0) {
					throw new \Exception('Device ID not created');
				}
			}
	
			DB::commit();
		}
		catch(\Exception $e) 
		{
			DB::rollback();
			$errMsg = $e->getMessage();
			return false;			
		}
	}

	public function validSystemInit($systemId, &$errMsg) {

		$system = DB::table('a_systems')->where('id', '=', $systemId)->
			where('user_id', '=', $this->userId)->first();
		if(!$system) {
			return false;
		}

		//rooms
		$rooms = DB::table('a_rooms')->where('system_id', '=', $systemId)->get();
		
		$lenRoom = 0;
		if($rooms) $lenRoom = count($rooms);

		try
		{

			DB::begintransaction();

			for($i = 0; $i < $lenRoom; $i++) {

				//devices
				$mainDev = DB::table('a_devices')->where('room_id', '=', $rooms[$i]->id)->
					where('id', array($rooms[$i]->main_device_id))->first();

				if($mainDev) {
					continue;
				}

				ErrorDebug::write('converted');

				$roomId = $rooms[$i]->id;

				$urcDev = new URCDeviceData($roomId);
				$mainDevId = $urcDev->repairMainDevice($rooms[$i]->main_device_id);
				if($mainDevId < 0) {
					throw new \Exception('Device ID not created');
				}

				//delete existing main buttons
				DB::table('a_btns')->where('room_id', '=', $roomId)->
					where('device_id', '=', $mainDevId)->delete();

				//add system off
				$urcBtn = new URCBtnData($roomId, -1);
				$macro = '';
				$urcBtn->newHardBtn(URCValues::BTN_SYSTEM_OFF, URCValues::BTN_LABEL_SYSTEM_OFF, $macro);
					
				//delete devices
				$devices = DB::table('a_devices')->where('room_id', '=', $roomId)->get();
				foreach($devices as $device) {

					if($device->id == $mainDevId) {
						continue;
					}

					//delete device 
					DB::table('a_devices')->where('room_id', '=', $roomId)->
						where('id', '=', $device->id)->delete();
					
					//delete connected Device 
					DB::table('a_keys_db')->where('room_id', '=', $roomId)->
						where('device_id', '=', $device->id)->delete();

					//delete keyboard data
					DB::table('a_con_db')->where('room_id', '=', $roomId)->
						where('device_id', '=', $device->id)->delete();
					
					//delete pages and btns
					//DB::table('a_pages')->where('room_id', '=', $this->roomId)->
					//	where('device_id', '=', $deviceId)->delete();

					DB::table('a_btns')->where('room_id', '=', $roomId)->
						where('device_id', '=', $device->id)->delete();
				}
			}
	
			DB::commit();
		}
		catch(\Exception $e) 
		{
			DB::rollback();
			$errMsg = $e->getMessage();
			return false;			
		}
	}

	//return : new system id
	public function createSystem($bstationType, $bstationName, $bstationMac,
		$systemName, $roomName, $controllerId, $timezoneId, $timezoneDst, $timeType,
		$cAddress, $cName, $cPhone, $dealerName){

		$systemId = -1;
		$deviceId = -1;

		try
		{

			DB::begintransaction();

			$systemId = $this->newSystem($systemName, $controllerId, $timezoneId, $timezoneDst, $timeType, URCValues::HOME_BTN_OPT_TOP,
				$cAddress, $cName, $cPhone, $dealerName);
			if($systemId < 0) {
				throw new \Exception('System ID not created');
			}

			$room = new URCRoomData($systemId);
			$roomId = $room->newRoom(1, $bstationType, $bstationName, $bstationMac, $roomName);
			if($roomId < 0) {
				throw new \Exception('Room ID not created');
			}

			$urcDev = new URCDeviceData($roomId);
			$deviceId = $urcDev->newMainDevice();
			if($deviceId < 0) {
				throw new \Exception('Device ID not created');
			}

			//set Main Device ID
			if($room->setMainDeviceId($roomId, $deviceId) == false) {
				throw new \Exception('fail to set the Main device id');
			}
			//system button
			$urcBtn = new URCBtnData($roomId, -1);
			$macro = '';
			$urcBtn->newHardBtn(URCValues::BTN_SYSTEM_OFF, URCValues::BTN_LABEL_SYSTEM_OFF, $macro);
			
			DB::commit();
		}
		catch(\Exception $e) 
		{
			DB::rollback();
			ErrorDebug::write($e->getMessage());
			$systemId = -1;				
		}
		
		return $systemId;
	}

	public function changeSystem($user, $systemId, $orgControllerId, $orgRoomId, $bstationMacOrg, $newModelType, $bstationMacNew, $newControllerId) {

		$username = $user->username;
		$password = Crypt::decrypt($user->password);
		//$sipId = $user->sip_id;

		//$system = DB::table('a_systems')->where('id', '=', $systemId)->
		//	where('user_id', '=', $this->userId)->first();

		$chkExisting = DB::table('a_bstations')->where('mac', '=', $bstationMacNew)->first();
		if($chkExisting) {
			$roomChk = DB::table('a_rooms')->where('id', '=', $chkExisting->room_id)->first();
			if(!$roomChk || $roomChk->system_id != $systemId) {
				if($this->deleteBStationFromOther($chkExisting) == false) {
					return false;
				}
				$chkExisting = null;
			}		
		}

		//$bstationMgr = new BStationManager(URCValues::WAIT_SEC);	
		try
		{		
			DB::begintransaction();
					
			if($chkExisting) {

				//change system info			
				DB::table('a_systems')->where('id', '=', $systemId)->
					update(array('controller_id' => $newControllerId));

				//change master
				if(strlen($bstationMacOrg) <= 0) {
					DB::table('a_bstations')->where('mac', '=', $bstationMacNew)->
						update(array('master' => 1, 'type' => $newModelType));
				}
				else {
					if($bstationMacOrg != $bstationMacNew) {
						DB::table('a_bstations')->where('mac', '=', $bstationMacOrg)->
							update(array('master' => 0));

						DB::table('a_bstations')->where('mac', '=', $bstationMacNew)->
							update(array('master' => 1, 'type' => $newModelType));
					}
				}				
			}
			else {
				
				//change system info			
				DB::table('a_systems')->where('id', '=', $systemId)->
					update(array('controller_id' => $newControllerId));
				if(strlen($bstationMacOrg) > 0) {
					//change
					DB::table('a_bstations')->where('mac', '=', $bstationMacOrg)->
						update(array('mac' => $bstationMacNew, 'type' => $newModelType));

					//change device info
					DB::table('a_devices')->where('room_id', '=', $orgRoomId)->
						where('target_addr', '=', $bstationMacOrg)->update(array('target_addr' => $bstationMacNew));
				}
				else {
					//add
					DB::table('a_bstations')->insert(array('system_id' => $systemId, 'room_id' => $orgRoomId,
						'mac' => $bstationMacNew, 'type' => $newModelType, 'name' => $newModelType, 'master' => 1));
				}
			}
				
			DB::commit();
		}
		catch(\Exception $e) 
		{
			DB::rollback();
			return false;				
		}
		
		return true;
	}

	public function destroySystem($systemId) {
		
		try
		{
			DB::begintransaction();

			DB::table('a_systems')->where('id', '=', $systemId)->delete();

			$rooms = DB::table('a_rooms')->where('system_id', '=', $systemId)->get();
			
			$roomObj = new URCRoomData($systemId);

			foreach($rooms as $room) {
				$roomObj->deleteRoom($room->id);
			}
			/*
			$lenRoom = 0;
			if($rooms) $lenRoom = count($rooms);
			for($i = 0; $i < $lenRoom; $i++) {
				
				$roomObj->deleteRoom($rooms[$i]->id);
			}
			*/
			
			DB::table('a_rooms')->where('system_id', '=', $systemId)->delete();

			DB::table('a_download')->where('system_id', '=', $systemId)->delete();

			DB::table('a_variables')->where('system_id', '=', $systemId)->delete();

			DB::table('a_amazon_system')->where('system_id', '=', $systemId)->delete();

			DB::commit();
		}
		catch(\Exception $e) 
		{
			DB::rollback();
			return false;				
		}
		
		return true;
	}

	public function deleteSystemFromDownData($systemId) {

		$downData = DB::table('a_download')->where('id', '=', $this->userId)->
			where('type', '=', URCValues::DOWN_TYPE_CLIENT_SYSTEMS)->first();

		if(!$downData || !$downData->link_data || strlen($downData->link_data) < 5) {
			return;
		}

		$data = json_decode($downData->link_data);

		$count = count($data->systems);
		for($i = 0; $i < $count; $i++) {
			if($data->systems[$i]->id != $systemId) {
				continue;
			}
			
			array_splice($data->systems, $i, 1);
			DB::table('a_download')->where('id', '=', $this->userId)->
				where('type', '=', URCValues::DOWN_TYPE_CLIENT_SYSTEMS)->update(array('link_data' => json_encode($data)));
				
			return;
		}
	}

	public function editSystem($systemId, $systemName) {
		
		$updatedRow = DB::table('a_systems')->where('id', '=', $systemId)->
			where('user_id', '=', $this->userId)->update(array('name' => $systemName));
		
		if($updatedRow <= 0)
			return false;
		
		return true;
	}

	public function getSystem($systemId) {

		$system = DB::table('a_systems')->where('id', '=', $systemId)->
			where('user_id', '=', $this->userId)->first();
		if(!$system)
			return false;

		$systemObj = new stdClass;
		$systemObj->id = (int) $systemId;
		$systemObj->name = $system->name;
		$systemObj->time_type = $system->time_type;
		$systemObj->created_at = $system->created_at;
		$systemObj->updated_at = $system->updated_at;

		if($system->timezone_id >= 0) {
			$timezone = DB::table('timezone')->where('id', '=', $system->timezone_id)->
				select('id', 'name', 's_time', 'd_bias')->first();
			if($timezone) {
				$systemObj->timezone = new stdClass;
				$systemObj->timezone->data = $timezone;
				$systemObj->timezone->dst = $system->timezone_dst;
			}
		}
		unset($system->timezone_id);
		unset($system->timezone_dst);		

		//homebutton Option
		$systemObj->home_btn_option = $system->home_btn_option;

		//variables
		$systemObj->variables = $this->getVariables($systemId);

		$systemObj->ext_service = array();
		//amazon echo
		$amazonObj = new URCAmazonData($systemId);
		$amazonService = $amazonObj->getServiceObj();
		if($amazonService) {
			$systemObj->ext_service[] = $amazonService;
		}

		//rooms
		$systemObj->rooms = array();
		$rooms = DB::table('a_rooms')->where('system_id', '=', $systemId)->get();
		
		$lenRoom = 0;
		if($rooms) $lenRoom = count($rooms);

		for($i = 0; $i < $lenRoom; $i++) {

			$systemObj->rooms[$i] = $rooms[$i];
			unset($systemObj->rooms[$i]->system_id);
			unset($systemObj->rooms[$i]->device_id_start);
			//unset($systemObj->rooms[$i]->master);
			
			$roomObj = &$systemObj->rooms[$i];

			//remotes
			$roomObj->remotes = array();

			$remotes = DB::table('a_remotes')->where('room_id', '=', $rooms[$i]->id)->get();

			$lenRemote = 0;
			if($remotes) $lenRemote = count($remotes);

			for($i2 = 0; $i2 < $lenRemote; $i2++) {

				$roomObj->remotes[$i2] = $remotes[$i2];
				unset($roomObj->remotes[$i2]->room_id);
			}

			//bstations
			$roomObj->bstations = array();

			$bstations = DB::table('a_bstations')->where('room_id', '=', $rooms[$i]->id)->get();

			$lenBStation = 0;
			if($bstations) $lenBStation = count($bstations);

			for($i2 = 0; $i2 < $lenBStation; $i2++) {

				$roomObj->bstations[$i2] = $bstations[$i2];
				unset($roomObj->bstations[$i2]->room_id);
				unset($roomObj->bstations[$i2]->system_id);
			}

			//schedule event
			$roomObj->scheEvent = array();
			$events = DB::table('a_events')->where('room_id', '=', $rooms[$i]->id)->
				orderBy('order', 'asc')->get();
			$lenEvent = 0;
			if($events) $lenEvent = count($events);

			for($i2 = 0; $i2 < $lenEvent; $i2++) {

				$roomObj->scheEvent[$i2] = $events[$i2];
				unset($roomObj->scheEvent[$i2]->room_id);
			}

			//devices
			$roomObj->devices = array();

			$devices = DB::table('a_devices')->where('room_id', '=', $rooms[$i]->id)->
				whereNotIn('id', array($rooms[$i]->main_device_id))->get();//not needed system(please delete system_id in the a_devices)

			$lenDev = 0;
			if($devices) $lenDev = count($devices);
			for($i2 = 0; $i2 < $lenDev; $i2++) {

				$devices[$i2]->exist_vol = URCDeviceData::isExistVol($devices[$i2]);

				$roomObj->devices[$i2] = $devices[$i2];
				unset($roomObj->devices[$i2]->room_id);
				unset($roomObj->devices[$i2]->page_id_start);
				unset($roomObj->devices[$i2]->btn_id_start);
			}

			//twoway_devices
			$roomObj->twoway_devices = array();

			$twoway_devices = DB::table('a_twoway_devices')->where('room_id', '=', $rooms[$i]->id)->get();

			$lenDev = 0;
			if($twoway_devices) $lenDev = count($twoway_devices);
			for($i2 = 0; $i2 < $lenDev; $i2++) {

				$roomObj->twoway_devices[$i2] = $twoway_devices[$i2];
				unset($roomObj->twoway_devices[$i2]->room_id);

				$varDecode = json_decode($roomObj->twoway_devices[$i2]->variables);
				$roomObj->twoway_devices[$i2]->variables = $varDecode;

				$dataDecode = json_decode($roomObj->twoway_devices[$i2]->data);
				$roomObj->twoway_devices[$i2]->data = $dataDecode;

				$extraDecode = json_decode($roomObj->twoway_devices[$i2]->extra_info);
				$roomObj->twoway_devices[$i2]->extra_info = $extraDecode;
				//unset($roomObj->twoway_devices[$i2]->data);

				unset($roomObj->twoway_devices[$i2]->auto_wait);
				unset($roomObj->twoway_devices[$i2]->edit_type);
				unset($roomObj->twoway_devices[$i2]->popup);
				unset($roomObj->twoway_devices[$i2]->activity);
				unset($roomObj->twoway_devices[$i2]->macro);
			}

			//amazon
			if($amazonService) {
				
				$roomObj->amazon_echo = new stdClass;
				$roomObj->amazon_echo->scenes = $amazonObj->getScenes($rooms[$i]->id);
				$roomObj->amazon_echo->link_code = $amazonService->link_code;
			}
		}

		return $systemObj;
	}

	public function newSystem($systemName, $controllerId, $timezoneId, $timezoneDst, $timeType, $homeBtnOption,
		$cAddress, $cName, $cPhone, $dealerName) {

		$systemId = DB::table('a_systems')->insertGetId(array('user_id' => $this->userId, 'name' => $systemName, 'controller_id' => $controllerId, 
			'timezone_id' => $timezoneId, 'timezone_dst' => $timezoneDst, 'time_type' => $timeType, 'home_btn_option' => $homeBtnOption,
			'c_address' => $cAddress, 'c_name' => $cName, 'c_phone' => $cPhone, 'installer_name' => $dealerName, 
			'created_at' => date('Y-m-d H:i:s'), 'updated_at' => date('Y-m-d H:i:s')));
		
		return $systemId;
	}

	public function applyDevicesAddr($systemId, $arDevice) {

		//get rooms
		$rooms = DB::table('a_rooms')->where('system_id', '=', $systemId)->get();

		foreach($arDevice as $device) {

			$found = false;
			foreach($rooms as $room) {
				if($room->id == $device->roomId) {
					$found = true;
					break;
				}
			}

			if(!$found) {
				return false;
			}
		}

		try
		{
			DB::begintransaction();

			foreach($arDevice as $device) {

				$target = $device->target;
				if($target->type == URCValues::DB_TYPE_IP ||
					$target->type == URCValues::DB_TYPE_UDP) {
					$updatedRow = DB::table('a_devices')->where('room_id', '=', $device->roomId)->
						where('id', '=', $device->deviceId)->update(
							array('target_type' => $target->type, 'target_addr' => $target->addr, 'target_port' => $target->port));
				}
				else {
					$updatedRow = DB::table('a_devices')->where('room_id', '=', $device->roomId)->
						where('id', '=', $device->deviceId)->update(
							array('target_type' => $target->type, 'target_addr' => $target->addr, 'target_port' => $target->port));
				}
			}

			DB::commit();
		}
		catch(\Exception $e) 
		{
			DB::rollback();
			return false;
		}
		
		return true;
	}

	public static function getControllerId($userId, $systemId) {
		
		$system = DB::table('a_systems')->where('id', '=', $systemId)->
			where('user_id', '=', $userId)->first();
		if(!$system) {
			return false;
		}

		return $system->controller_id;
	}

	/*
	public function getControllersByUserId() {

		$arController = array();

		$systems = $this->getSystems();
		foreach($systems as $system) {

			$bstation = DB::table('a_bstations')->where('system_id', '=', $system->id)->
				where('master', '=', 1)->first();

			if($bstation) {
				$arController[] = (object)array('id' => $system->controller_id, 'mac' => $bstation->mac, 'name' => $system->name);
			}
		}

		return $arController;
	}
	*/

	public function setHomeBtnOption($systemId, $option) {

		$updatedRow = DB::table('a_systems')->where('id', '=', $systemId)->
			where('user_id', '=', $this->userId)->update(array('home_btn_option' => $option));
		
		if($updatedRow <= 0)
			return false;
		
		return true;
	}

	public function getVariables($systemId) {
		
		$vars = DB::table('a_variables')->where('system_id', '=', $systemId)->orderBy('name', 'asc')->get();
		foreach($vars as $var) {
			unset($var->system_id);
		}
		return $vars;
	}

	public function addVariable($systemId, $name, $type, $value, &$errMsg) {

		$system = DB::table('a_systems')->where('id', '=', $systemId)->
			where('user_id', '=', $this->userId)->first();
		if(!$system) {
			$errMsg = "can't find the system";
			return false;
		}
		
		$existingVar = DB::table('a_variables')->where('system_id', '=', $systemId)->where('name', '=', $name)->first();
		if($existingVar) {
			$errMsg = "already existing variable";
			return false;
		}
		
		$retVarId = $system->var_id_start;
		try
		{
			DB::begintransaction();
			
			DB::table('a_variables')->insert(array('id' => $system->var_id_start, 'system_id' => $systemId, 'name' => $name, 'type' => $type, 'value' => $value));
			$system->var_id_start++;

			DB::table('a_systems')->where('id', '=', $systemId)->
				where('user_id', '=', $this->userId)->update(array('var_id_start' => $system->var_id_start));

			DB::commit();
		}
		catch(\Exception $e) 
		{
			DB::rollback();

			$errMsg = "db error";
			return false;
		}

		return $retVarId;
	}

	public function delVariables($systemId, $varId) {
		
		DB::table('a_variables')->where('system_id', '=', $systemId)->where('id', '=', $varId)->delete();
	}

	public function setVariable($systemId, $varId, $name, $type, $value, $errMsg) {

		$existingVar = DB::table('a_variables')->where('system_id', '=', $systemId)->where('name', '=', $name)->first();
		if(!$existingVar) {
			$errMsg = "not existing variable";
			return false;
		}
		
		DB::table('a_variables')->where('id', '=', $varId)->update(array('system_id' => $systemId, 'name' => $name, 'type' => $type, 'value' => $value));
		
		return $varId;
	}

	public function setDealer($systemId, $dealerId, $dealerGrpId, &$errMsg) {
		
		$system = DB::table('a_systems')->where('id', '=', $systemId)->
				where('user_id', '=', $this->userId)->first();
		if(!$system) {
			$errMsg = "can't find the system";
			return false;
		}

		if(strlen($system->dealer_id) > 0) {
			$errMsg = "already assigned to a dealer";
			return false;
		}

		DB::table('a_systems')->where('id', '=', $systemId)->
				where('user_id', '=', $this->userId)->update(
					array('dealer_id' => $dealerId, 'dealer_grp_id' => $dealerGrpId));
	
		return true;
	}

}

class URCTwowayDBMgr {

	/*
		//target_type => 0 : NONE, 1:MAC, 2:IP, 4:Service
		//reserved name => mac->mac address, device_ip -> ip addredss, device_port -> ip port, 
		//				=> username -> username, password -> password
		{
			"variables" : [ 
				{ "name" : "username", "attr" : "", "caption" : "caption text"},
			 	{ "name" : "password", "attr" : "p", "caption" : "caption text|caption text2"},
			 	{ "name" : "other1", "attr" : "m", "height" : 3, "caption" : "others dsfdsfs"},
			 	{ "name" : "other2", "attr" : "", "default" : "test", "caption" : "other2" }
			],

			"script" : "sonos.tcl", "parameter" : "<<mac>>   <<username>> <<password>> <<other2>>", "target_type" : 2,
			"twoway_modules"  : [
				{ "module" : "Sonos", "script" : "sonos_module.tcl", "parameter" : "COUNT=20 <<password>>", "data_file" : "Sonos.dat" }
			]
		}		
	*/
	

	var $errMsg;
	var $username;
	var $usr_level;

	function __construct($username, $usr_level) {	
		$this->username = $username;
		$this->usr_level = $usr_level;
		$this->errMsg = '';
	}

	public function getErrMsg() { return $this->errMsg; }

	public function isLevelUser() {

		if($this->usr_level < URCValues::LOGIN_ADMIN) {
			return false;
		}

		return true;
	}

	public function checkValidData(&$dbData) {
		
		if(!isset($dbData->script) || !isset($dbData->parameter) || !isset($dbData->variables) || 
			!isset($dbData->target_type) || !isset($dbData->twoway_modules)) {
			$this->errMsg = 'error data format-check (script, parameter, variables, target_type, twoway_modules)';
			return false;
		}	

		switch($dbData->target_type & 0xffff)
		{
		case URCValues::TWPWAY_TYPE_NONE:
		case URCValues::TWOWAY_TYPE_MAC:
		case URCValues::TWOWAY_TYPE_IP:
		case URCValues::TWOWAY_TYPE_SERVICE:
			break;
		default:
			$this->errMsg = 'target_type in data is wrong';
			return false;
		}

		return true;
	}

	//alll ID must be Integer
	public function getTwowayModelData($categoryId, $categoryName, $brandId, $brandName, $modelId, $modelName, &$data) {

		if(!$this->isLevelUser()) {
			$this->errMsg = 'not valid user for this function';
			return false;
		}

		//check model
		$model = DB::table('a_db2_models')->where('id', '=', $modelId)->where('name', '=', $modelName)->
			where('brand_id', '=', $brandId)->select('version', 'major', 'name', 'target_type', 'script', 'cmds', 'variables', 'parameter', 'twoway_modules')->first();		
		if(!$model) {
			$this->errMsg = 'not existing model';
			return false;
		}
			
		//check brand
		$brands = DB::table('a_db2_brands')->where('id', '=', $brandId)->where('name', '=', $brandName)->
			where('category_id', '=', $categoryId)->first();
		if(!$brands) {
			$this->errMsg = 'not existing brand';
			return false;
		}
		
		//check category
		$categories = DB::table('a_db2_categories')->where('id', '=', $categoryId)->where('name', '=', $categoryName)->first();
		if(!$categories) {
			$this->errMsg = 'not existing category';
			return false;
		}		
		

		$data = $model;
		if(strlen($data->cmds) > 0) {
			$data->cmds = json_decode($data->cmds);
		}
		else {
			unset($data->cmds);
		}
		$data->variables = json_decode($data->variables);
		$data->twoway_modules = json_decode($data->twoway_modules);

		return true;
	}

	//alll ID must be Integer
	public function addTwowayModelToDB($categoryId, $categoryName, $brandId, $brandName, $modelId, $modelName, 
		$data, $version, $major) {

		//ErrorDebug::write('storeDevice');
		//ErrorDebug::write($jsonData);

		if(!$this->isLevelUser()) {
			$this->errMsg = 'not valid user for this function';
			return false;
		}	
		
		$dbData = json_decode($data);
		if($this->checkValidData($dbData) == false) {
			return false;
		}
		
		//check model
		$model = DB::table('a_db2_models')->where('id', '=', $modelId)->
			orWhere(function($query) use ($brandId, $modelName) {
				$query->where('brand_id', '=', $brandId)->where('name', '=', $modelName);
			})->first();
		if($model) {
			$this->errMsg = 'already existing model';
			return false;
		}
			
		//check brand
		$isMakeBrand = true;
		$brands = DB::table('a_db2_brands')->where('id', '=', $brandId)->
			orWhere(function($query) use ($categoryId, $brandName) {
				$query->where('category_id', '=', $categoryId)->where('name', '=', $brandName);
			})->get();
		if($brands) {
			$cnt = count($brands);
			switch($cnt)
			{
			case 0:
				break;
			case 1:
				if($brands[0]->id !== $brandId || $brands[0]->name !== $brandName) {
					$this->errMsg = "doesn't match the brand and id";
					return false;
				}
				$isMakeBrand = false;
				break;
			default://id and brand is different
			 	$this->errMsg = "doesn't match the brand and id";
				return false;
			}
		}			

		//check category
		$categories = DB::table('a_db2_categories')->where('id', '=', $categoryId)->orWhere('name', '=', $categoryName)->get();
		$isMakeCategory = true;
		if($categories) {
			$cnt = count($categories);
			switch($cnt)
			{
			case 0:
				break;
			case 1:
				if($categories[0]->id !== $categoryId || $categories[0]->name !== $categoryName) {
					$this->errMsg = "doesn't match the category and id";
					return false;
				}
				$isMakeCategory = false;
				break;
			default://id and brand is different
				$this->errMsg = "doesn't match the category and id";
				return false;
			}
		}		

		//add
		try
		{
			DB::begintransaction();

			if($isMakeCategory) {
				DB::table('a_db2_categories')->insert(array('id' => $categoryId, 'name' => $categoryName));
			}

			if($isMakeBrand) {
				DB::table('a_db2_brands')->insert(array('id' => $brandId, 'category_id' => $categoryId, 'name' => $brandName));
			}

			$cmdsData = '';
			if(isset($dbData->cmds)) {
				$cmdsData = json_encode($dbData->cmds);
			}

			DB::table('a_db2_models')->insert(array('id' => $modelId, 'brand_id' => $brandId, 'version' => $version, 'major' => $major, 'name' => $modelName,
				'target_type' => $dbData->target_type, 'script' => $dbData->script, 'variables' => json_encode($dbData->variables), 'parameter' => $dbData->parameter, 
				'twoway_modules' => json_encode($dbData->twoway_modules),
				'cmds' => $cmdsData));

			DB::commit();
		}
		catch(\Exception $e) 
		{
			DB::rollback();
			$this->errMsg = "DB error";
			return false;
		}

		return true;
	}

	public function setTwowayModelToDB($categoryId, $categoryName, $brandId, $brandName, $modelId, $modelName, 
		$data, $version, $major) {

		//ErrorDebug::write('storeDevice');
		//ErrorDebug::write($jsonData);

		if(!$this->isLevelUser()) {
			$this->errMsg = 'not valid user for this function';
			return false;
		}
		
		$dbData = json_decode($data);
		if($this->checkValidData($dbData) == false) {
			return false;
		}
		
		//check model
		$model = DB::table('a_db2_models')->where('id', '=', $modelId)->where('name', '=', $modelName)->
			where('brand_id', '=', $brandId)->first();
		if(!$model) {
			$this->errMsg = 'not existing model';
			return false;
		}
			
		//check brand
		$brands = DB::table('a_db2_brands')->where('id', '=', $brandId)->where('name', '=', $brandName)->
			where('category_id', '=', $categoryId)->first();
		if(!$brands) {
			$this->errMsg = 'not existing brand';
			return false;
		}
		
		//check category
		$categories = DB::table('a_db2_categories')->where('id', '=', $categoryId)->where('name', '=', $categoryName)->first();
		if(!$categories) {
			$this->errMsg = 'not existing category';
			return false;
		}		

		$cmdsData = '';
		if(isset($dbData->cmds)) {
			$cmdsData = json_encode($dbData->cmds);
		}
		
		//add
		try
		{
			DB::begintransaction();

			DB::table('a_db2_models')->where('id', '=', $modelId)->update(array('brand_id' => $brandId, 'version' => $version, 'major' => $major, 'name' => $modelName,
				'target_type' => $dbData->target_type, 'script' => $dbData->script, 'variables' => json_encode($dbData->variables), 'parameter' => $dbData->parameter, 
				'twoway_modules' => json_encode($dbData->twoway_modules),
				'cmds' => $cmdsData));

			DB::commit();
		}
		catch(\Exception $e) 
		{
			DB::rollback();
			return false;
		}

		return true;
	}

}