'use strict';
/**
 * @ngdoc controller
 * @name EditMacroRoomController
 * @description
 *  room 선택 화면
 */
app.controller('EditMacroRoomController', function ($scope, $state, toastr, Systems) {
	$scope.system = Systems.getCurrentSystem();


	$scope.doNext = function() {
		// room 정보 얻어와서 저장
		return Systems.updateRoomDevices($scope.addMacro.room.id)
		.then(function(data) {
			var roomDevices = Systems.getRoomDevices();
			$scope.addMacro.room.devices = roomDevices.devices;

			// dev_type이 twoway(1)인 device를 모두 제거하는 과정에서 $scope.addMacro.room.devices 에서 SNP-2 가 제거되는데 SNP-2 가 있는 목록이 "Add jump to" 에서 필요해서 copy 를 만듬
			$scope.addMacro.room.devicesAndSNP2 = angular.copy(roomDevices.devices);

			// twoway_devices 중 TRF-ZW 추가한 device 목록 생성
			$scope.addMacro.room.allDevices = angular.copy($scope.addMacro.room.devices);

			_.each($scope.system.rooms, function(room) {
				var trfzw = _.find(room.twoway_devices, {model: 'TRF-ZW1'});
				if (trfzw) {
					if (!trfzw.data) {
						trfzw.data = [];
					}
					$scope.addMacro.room.allDevices.push(trfzw);

					return false;
				}
			});

			$state.go('menu.advanced.edit-macros.macro-simulator', {roomId: $scope.addMacro.room.id});
		})
		.catch(toastr.error);
	};
});

/**
 * @ngdoc controller
 * @name MacroSimulatorController
 * @description
 *  macro 를 수정할 button, device 선택 화면
 */
app.controller('MacroSimulatorController', function ($scope, $state, $modal, toastr, Systems) {
  // Advanced Menu 의 Edit your automated activities 메뉴를 클릭해서 들어온 경우
  //   => currentRoom 을 선택된 room 으로 설정함
  $scope.addMacro.room = $scope.room;

  // 아래의 코드는 EditMacroRoomController 의 doNext 에서 하는 동작임
  Systems.updateRoomDevices($scope.addMacro.room.id)
    .then(function (data) {
      var roomDevices = Systems.getRoomDevices();
      $scope.addMacro.room.devices = roomDevices.devices;

      // dev_type이 twoway(1)인 device를 모두 제거하는 과정에서 $scope.addMacro.room.devices 에서 SNP-2 가 제거되는데 SNP-2 가 있는 목록이 "Add jump to" 에서 필요해서 copy 를 만듬
      $scope.addMacro.room.devicesAndSNP2 = angular.copy(roomDevices.devices);

      // twoway_devices 중 TRF-ZW 추가한 device 목록 생성
      $scope.addMacro.room.allDevices = angular.copy($scope.addMacro.room.devices);

      _.each($scope.system.rooms, function (room) {
        var trfzw = _.find(room.twoway_devices, {model: 'TRF-ZW1'});
        if (trfzw) {
          if (!trfzw.data) {
            trfzw.data = [];
          }
          $scope.addMacro.room.allDevices.push(trfzw);

          return false;
        }
      });

      $state.go('menu.advanced.edit-macros.macro-simulator', {roomId: $scope.addMacro.room.id});
    })
    .catch(toastr.error);

	$scope.editMacro.currentPage = 1;

	//$scope.addMacro.room.devices = devices;

	function updateMainDevice() {
		// main device 얻어와서 저장
		Systems.updateMainDevice($scope.addMacro.room.id).then(function(data) {
			console.log(data);
			$scope.editMacro.mainDevice = data;
			$scope.client.page = angular.copy($scope.editMacro.mainDevice.pages[$scope.editMacro.currentPage - 1]);
			var numPages = $scope.editMacro.mainDevice.pages.length;
			$scope.editMacro.totalItems = numPages * 6;
		})
		.catch(toastr.error);
		
		updatePowerMacro();
	}

  updateMainDevice();

	function isJsonString(str) {
		try {
			JSON.parse(str);
		} catch (e) {
			return false;
		}
		return true;
	}

	$scope.isJsonString = isJsonString;

	$scope.editPowerMacro = function() {
		$scope.macroType.id = 0;

		var roomId = $scope.addMacro.room.id;
		// 해당 room 의 power macro 데이터 얻어와서 저장
		Systems.updateCurrentMacroForPower(roomId).then( function(data) {
			console.log(data);
			$scope.addMacro.steps = cleanUp('macro', roomId, data.macro);
			//$scope.addMacro.autoWait = data.auto_wait ? true:false;
			$scope.addMacro.doneScreen.devices = cleanUp('activity', roomId, data.activity);
			$scope.addMacro.disablePopup = data.popup ? false:true;
			$state.go('menu.advanced.edit-macros.finish');
		}).catch(function (error) {
			alert(error);
		});
	};

	function cleanUp(type, roomId, arr) {
		//console.log(arr);
		var filteredSteps = [];
		var steps =  isJsonString(arr) ? JSON.parse(arr):arr ;
		_.forEach(steps, function (step) {
			var device;
			var variable;

			if (type === 'macro') {
				if (step.type === 1) {
					device = Systems.getDevice(roomId, step.device_id);
					if (device) {
						step.name = device.name + ': ' + _.find(device.funcs, {'id': step.func}).name;
						filteredSteps.push(step);
					}
				} else if (step.type === 2) {
					step.name = 'Delay ' + step.value/1000 + ' seconds';
					filteredSteps.push(step);
				} else if (step.type === 3 && step.to.type === 1) {
					//device = Systems.getDevice(roomId, step.to.value);
					device =  _.find($scope.addMacro.room.devicesAndSNP2, { 'id': step.to.value });		// Systems.getDevice 에서 device 를 찾으면, "dev_type이 twoway(1)인 device를 모두 제거." 주석 처리된 부분에 의해 Add jump to 에서 추가한 SNP-2 가 보이지 않게 되어서 $scope.addMacro.room.devicesAndSNP2 에서 device 를 찾음
					if (device) {
						step.name = 'Jump to ' + device.name;
						filteredSteps.push(step);
					}
				} else if (step.type === 4) {
					variable = _.find($scope.system.variables || $scope.system.rooms[0].variables, {'id': step.cond.id});		// virtual editor 에는 system 에 variables 가 없어서 rooms[0].variables 를 사용. virtual editor 에는 room 이 1개만 있어서 rooms[0] 을 사용함.
					if (variable) {
						if(variable.type == 0){
							name = 'If: ' + variable.name + ', ' + (step.cond.value == 1 ? 'True':'False');
						} else{
							name = 'If: ' + variable.name + ' ' +  step.cond.operate + ' ' + step.cond.value;
						} 

						step.name = name;

						step.steps = [{name:'True', steps:[]}, {name:'False', steps:[]}];

						filteredSteps.push(step);

						if(step.true){
							step.steps[0].steps = cleanUp('macro', roomId, step.true);
						}

						if(step.false){
							step.steps[1].steps = cleanUp('macro', roomId, step.false);
						}
					}
				}
				else if (step.type === 5) {
					variable = _.find($scope.system.variables || $scope.system.rooms[0].variables, {'id': step.id});	// virtual editor 에는 system 에 variables 가 없어서 rooms[0].variables 를 사용. virtual editor 에는 room 이 1개만 있어서 rooms[0] 을 사용함.
					if (variable) {
						var dispValue = step.value;
						if(variable.type == 0){
							if(step.value == 0){
								dispValue = 'false' ;
							}
							else if(step.value == 1){
								dispValue = 'true' ;
							}
							else if(step.value == 2){
								dispValue = 'invert' ;
							}
						}

						step.name = 'VAR ' + variable.name + '= ' + dispValue;
						filteredSteps.push(step);
					}
				} else if (step.type === 16) {
					_.each($scope.system.rooms, function(room) {
						device = _.find(room.twoway_devices, {model: 'TRF-ZW1'});

						if (device) {
							var scene = _.find(device.data, {id: step.id});

							if (scene) {
								step.name = 'S : ' + scene.name + ' (' + scene.room + ')';
								filteredSteps.push(step);
							}

							return false;
						}
					});
				}
			} else {
				device = Systems.getDevice(roomId, step.device_id);
				if (device) {
					step.name = device.name;
					step.funcs = device.funcs;
					filteredSteps.push(step);
				}

			}
		});
		return filteredSteps;
	}



	$scope.editBtnMacro = function(btn) {
		//console.log(btn);
		var roomId = angular.copy($scope.addMacro.room.id);
		var activity =  btn.activity ? JSON.parse(btn.activity):[];

		$scope.addMacro.steps = cleanUp('macro', roomId, btn.macro);
		console.log('$scope.addMacro.steps=', $scope.addMacro.steps);
		//$scope.addMacro.autoWait = btn.auto_wait ? true:false;
		$scope.addMacro.doneScreen.devices = cleanUp('activity', roomId, activity);
		$scope.addMacro.disablePopup = btn.popup ? false:true;
		$scope.addMacro.linkId = btn.link_id;
		$scope.addMacro.btnId = btn.id;

	
		$scope.macroType.id = btn.link_id !== -1? 1:2;
		
		switch ($scope.macroType.id) {
			case 1:
				$scope.addMacro.currentDevice = _.find($scope.addMacro.room.devices, {'id': btn.link_id});
				break;
			case 2:
				$scope.addMacro.button.name = btn.display_text;
				break;
			default:
				break;
		}
		$state.go('menu.advanced.edit-macros.finish');
	};

	$scope.pageChanged = function(page) {
		$scope.client.page = angular.copy($scope.editMacro.mainDevice.pages[page - 1]);
	};
	
	function updatePowerMacro() {
		// 해당 room 의 power macro 데이터 얻어와서 저장
		Systems.updateCurrentMacroForPower($scope.addMacro.room.id).then( function(data) {
			$scope.powerMacro = data.macro;
		}).catch(function (error) {
			toastr.error(error);
		});
	}
	
	$scope.deleteMacro = function(mode, linkId, roomId, deviceId, btnId) {
		var handleSuccess = function(response) {
			if(response.data.result === true) {
				toastr.success('Automated Activity has been deleted');
				updateMainDevice();
			} else {
				toastr.error('Delete failed to work. Please try again.');
			}
		};

		var handleError = function(error){
			toastr.error(error, 'Error');
		};
		
		if (mode === 'power') {
			// 해당 room 의 power macro 삭제
			Systems.deletePowerMacro($scope.addMacro.room.id).then(handleSuccess, handleError);
		} else if (mode === 'device-btn') {
			if (linkId == '-1') {
				// button ID 에 해당하는 button 삭제
				Systems.deleteButtonMacro(roomId, deviceId, btnId).then(handleSuccess, handleError);
			} else {
				// 해당 device ID 와 연계된 button 의 macro 삭제
				Systems.deleteButtonMacroWithDevice(roomId, linkId).then(handleSuccess, handleError);
			}
		}
	};
	
	$scope.deleteMacroModal = function(mode, linkId, roomId, deviceId, btnId) {
		var scope = $scope.$new();
		scope.data = {
			mode: mode,
			linkId: linkId,
			roomId: roomId,
			deviceId: deviceId,
			btnId: btnId
		};
		
		var modal = $modal({
			scope: scope,
			template: 'views/modal-tpls/delete-macro.html',
			container: 'body',
			show: false
		});
		modal.$promise.then(modal.show);
	};

});

/**
 * @ngdoc controller
 * @name EditMacroController
 * @description
 *  macro device, commands 입력
 */
app.controller('EditMacroController', function ($scope, $timeout, $state, $modal, toastr, Devices, Systems) {

	$scope.selectedItem = {};

	$scope.remove = function(scope) {
		scope.remove();
	};

	$scope.options = {
		accept: function(sourceNodeScope, destNodesScope, destIndex) {
			//console.log('sourceNodeScope=', sourceNodeScope);
			//console.log('destNodesScope=', destNodesScope);
			if (sourceNodeScope.$modelValue.type == null || destNodesScope.nodropEnabled || destNodesScope.outOfDepth(sourceNodeScope)) {
				return false;
			}

	        var subDepth = 0;
	        function countSubDepth(scope) {
				var i, childNodesScope,
					count = 0,
					nodes = scope.childNodes();

				//console.log('childNodes=', nodes);

				for (i = 0; i < nodes.length; i++) {
					childNodesScope = nodes[i].$childNodesScope;

					if (childNodesScope && childNodesScope.childNodesCount() > 0) {
						count = 1;
						countSubDepth(childNodesScope);
					}
				}
				subDepth += count;				
			}

			var maxSubDepth = function (scope) {
				subDepth = 0;
				if (scope.hasChild()) {
					countSubDepth(scope.$childNodesScope);
					subDepth++;
				}
				return subDepth;
			};

			/*
			console.log('sourceNodeScope.childNodes()=', sourceNodeScope.childNodes());
			console.log('sourceNodeScope.childNodesCount()=', sourceNodeScope.childNodesCount());
			console.log('maxSubDepth(sourceNodeScope)=', maxSubDepth(sourceNodeScope));
			console.log('destNodesScope.depth()=', destNodesScope.depth());
			console.log('destNodesScope.maxDepth=', destNodesScope.maxDepth);
			console.log('destNodesScope.$treeScope.maxDepth=', destNodesScope.$treeScope.maxDepth);
			*/

			//angular-ui-tree module의 maxSubDepth function에서 sub depth count를 child node 존재 유무를 기준으로 함.
			//그래서 2depth인 tree인 경우 depth count를 0으로 return하여 outOfDepth function을 호출해도 제대로된 결과를 받지 못하고,
			// (max-depth -1) depth인 tree에 2depth의 tree를 drag/drop하면 삽입이 됨.
			//그래서, 별도의 maxSubDepth function을 구현함.
			var sumDepth =  (maxSubDepth(sourceNodeScope)+1) + destNodesScope.depth();
			var maxDepth = destNodesScope.maxDepth || destNodesScope.$treeScope.maxDepth;

			if(sumDepth  > maxDepth){
				return false;
			}

			return true;
		},
	};

	var getRootNodesScope = function() {
		return angular.element(document.getElementById("tree-root")).scope();
	};

	$scope.collapseAll = function() {
		var scope = getRootNodesScope();
		scope.collapseAll();
	};

	$scope.expandAll = function() {
		var scope = getRootNodesScope();
		scope.expandAll();
	};


	$scope.addStep = function (device, func, twowayDevice) {
		if (twowayDevice) {
			return {'name': 'S : ' + func.name + ' (' + func.room + ')', 'type': 16, 'sub_type': 'scene', 'id': func.id, 'cmd': 1 };		// 1 : Activate, 2 : Deactivate
		} else {
			return {'name': device.name + ': ' + func.name, 'type': 1, 'device_id': device.id, 'func': func.id };
		}
	};

	$scope.deleteAll = function() {
		var arr = $scope.addMacro.steps;
		while(arr.length > 0) {
			arr.pop();                     
		}
	};

	$scope.goBack = function() {
		$state.go('menu.advanced.edit-macros.macro-simulator', {roomId: $scope.addMacro.room.id});
	};

	$scope.doNext = function() {
		$state.go('menu.advanced.edit-macros.macro-done');
	};

	$scope.refreshScenes = function(device) {
		Devices.updateTwowayDevice($scope.addMacro.room.id, device.id)
			.then(function(data) {
				console.log(data);

				var item = _.where($scope.addMacro.room.allDevices, {'id': device.id})[0];
				item.data = data;
			}, function() {
				var modal = $modal({
					scope: $scope,
					title: "Couldn't refresh the list",
					container: '.editor-container',
					template: 'views/modal-tpls/refresh-the-list.html',
					show: false
				});

				modal.$promise.then(modal.show);
			})
			.catch(toastr.error);
	};

});

/**
 * @ngdoc controller
 * @name EditMacroDoneController
 * @description
 *  macro 설정 완료 화면
 */
app.controller('EditMacroDoneController', function ($scope, $state, toastr, Systems) {
	$scope.addMacro.doneScreen.index = 0;

	$scope.goBack = function() {
		$state.go('menu.advanced.edit-macros.finish');
	};

	function cleanUp(steps) {
		var filteredSteps = steps;
		_.forEach(filteredSteps, function (step) {
			delete step.name; 
			if(step.type == 4){
				console.log('cleanUp-step=', step);
				if(0 < step.steps[0].steps.length) {						
					step.steps[0].steps = cleanUp(step.steps[0].steps);
					step.true = angular.copy(step.steps[0].steps);					
				}
				if(0 < step.steps[1].steps.length) {
					step.steps[1].steps = cleanUp(step.steps[1].steps);
					step.false = angular.copy(step.steps[1].steps);					
				}
				delete step.steps;
			}
		});
		return filteredSteps;
	}

	$scope.doNext = function() {
		if ($scope.addMacro.disablePopup) {
			var steps =  angular.copy($scope.addMacro.steps);
			steps = cleanUp(steps);
			console.log('steps=', steps);

			//var autoWait = $scope.addMacro.autoWait ? 1:0;
			var jsonData = JSON.stringify( { auto_wait: 1 , edit_type: 1, popup: 0, activity: [], macro: steps } );
			console.log('jsonData=', jsonData);

			var handleSuccess = function(response) {
				if(response.data.result === true) {
					$state.go('menu.advanced.edit-macros.next-action');
				} else {
					toastr.error('Your edit/create action failed.  Please try again.');
				}
			};

			var handleError = function(error){
				toastr.error("Please try again");
			};

			if ($scope.macroType.id === 0) {
				// 해당 room 의 power macro 데이터 저장
				Systems.storePowerMacro($scope.addMacro.room.id, jsonData).then(handleSuccess, handleError);
			} else if ($scope.macroType.id === 1) {
				// 해당 device ID 와 연계된 button 의 데이터 저장
				Systems.storeDeviceButtonMacro($scope.addMacro.room.id, $scope.addMacro.linkId, jsonData).then(handleSuccess, handleError);
			} else {
				// button ID 에 해당하는 button 의 데이터 저장
				Systems.storeCustomButtonMacro($scope.addMacro.room.id, $scope.addMacro.room.main_device_id, $scope.addMacro.btnId, jsonData).then(handleSuccess, handleError);
			}
		} else {
			$state.go('menu.advanced.edit-macros.macro-commands');
		}
	};

});


app.controller('EditMacroCommandsController', function ($scope, $state, toastr, Systems) {

	$scope.goBack = function() {
		if ($scope.addMacro.doneScreen.index === 0) {
			$state.go('menu.advanced.edit-macros.macro-done' );
		} else {
			$scope.addMacro.doneScreen.index--;
		}
	};


	function cleanUp(steps) {
		var filteredSteps = steps;
		_.forEach(filteredSteps, function (step) {
			delete step.name; 
			if(step.type == 4){
				console.log('cleanUp-step=', step);
				if(0 < step.steps[0].steps.length) {						
					step.steps[0].steps = cleanUp(step.steps[0].steps);
					step.true = angular.copy(step.steps[0].steps);					
				}
				if(0 < step.steps[1].steps.length) {
					step.steps[1].steps = cleanUp(step.steps[1].steps);
					step.false = angular.copy(step.steps[1].steps);					
				}
				delete step.steps;
			}
		});
		return filteredSteps;
	}


	$scope.doNext = function() {
		var len = $scope.addMacro.doneScreen.devices.length;
		if ($scope.addMacro.doneScreen.index + 1 === len) {
			//var autoWait = $scope.addMacro.autoWait ? 1:0;
			var steps =  angular.copy($scope.addMacro.steps);
			steps = cleanUp(steps);
			console.log('steps=', steps);

			var activityData = angular.copy($scope.addMacro.doneScreen.devices);

			_.forEach(steps, function(step) { delete step.name; });
			_.forEach(activityData, function(activity) {
				activity.func = activity.func.id;
				delete activity.name;
				delete activity.repeat_min;
				delete activity.repeat_macro;
				delete activity.target_type;
				delete activity.target_addr;
				delete activity.target_port;
				delete activity.funcs;
			});

			var jsonData = JSON.stringify( { auto_wait: 1 , edit_type: 1, popup: 1, activity: activityData, macro: steps } );

			var handleSuccess = function(response) {
				if(response.data.result === true) {
					$state.go('menu.advanced.edit-macros.next-action');
				} else {
					toastr.error('Your edit/create action failed.  Please try again.');
				}
			};

			var handleError = function(error){
				toastr.error('Please try again');
			};

			if ($scope.macroType.id === 0) {
				Systems.storePowerMacro($scope.addMacro.room.id, jsonData).then(handleSuccess, handleError);
			} else if ($scope.macroType.id === 1) {
				Systems.storeDeviceButtonMacro($scope.addMacro.room.id, $scope.addMacro.linkId, jsonData).then(handleSuccess, handleError);
			} else {
				Systems.storeCustomButtonMacro($scope.addMacro.room.id, $scope.addMacro.room.main_device_id, $scope.addMacro.btnId, jsonData).then(handleSuccess, handleError);
			}
		} else {
			$scope.addMacro.doneScreen.index++;
		}

	};
});
