'use strict';
/**
 * @ngdoc service
 * @name Devices
 * @description
 *  device 관련 기능
 */
app.service('Devices', function ($rootScope, $http, $q, Rooms) {

	this.icons = [];
	this.menuBtnPages = [];
	this.hardBtnPages = [];
	this.currentData = {};
	this.functions = [];
	this.currentDevice = {};

	/**
	 * Learn codes from an IR remote 메뉴에 나오는 hard button 목록 설정
	 * @memberof Devices
	 */
	this.initHardBtnPages = function() {
		this.hardBtnPages = [{btns:[{name:'VOL +',id:275},{name:'PREV CH',id:278},{name:'CH +',id:279},{name:'VOL -',id:276},{name:'MUTE',id:277},{name:'CH -',id:280}]},{btns:[{name:'MENU',id:305},{name:'UP',id:322},{name:'GUIDE',id:304},{name:'LEFT',id:320},{name:'SELECT',id:324},{name:'RIGHT',id:321},{name:'INFO',id:306},{name:'DOWN',id:323},{name:'EXIT',id:307}]},{btns:[{name:'SKIP -',id:295},{name:'PLAY',id:288},{name:'SKIP +',id:294},{name:'REW',id:292},{name:'PAUSE',id:291},{name:'FWD',id:293},{name:'STOP',id:289},{name:'REC',id:296},{name:'YELLOW',id:548},{name:'BLUE',id:549},{name:'RED',id:550},{name:'GREEN',id:551}]},{btns:[{name:'1',id:337},{name:'2',id:338},{name:'3',id:339},{name:'4',id:340},{name:'5',id:341},{name:'6',id:342},{name:'7',id:343},{name:'8',id:344},{name:'9',id:345},{name:'/',id:346},{name:'0',id:336},{name:'ENT',id:348}]}];

	};

	/**
	 * icons 저장
	 * @memberof Devices
	 * @param {Array} icons icons array
	 */
	this.setIcons = function(icons) {
		this.icons = icons;
	};

	/**
	 * icons 얻기
	 * @memberof Devices
	 * @returns {Array} icons array
	 */
	this.getIcons = function() {
		return this.icons;
	};

	/**
	 * icon 목록이 있는 json 파일로부터 데이터 얻기
	 * @memberof Devices
	 * @returns {Promise} Future object
	 */
	this.getInfoJson = function() {
		return $http.get('/file/images/device_icons/info.json');
	};

	/**
	 * device data 저장
	 * @memberof Devices
	 * @param {Object} data device data
	 */
	this.setCurrentData = function(data) {
		this.currentData = data;
	};

	/**
	 * device data 얻기
	 * @memberof Devices
	 * @returns {Object}
	 */
	this.getCurrentData = function() {
		return this.currentData;
	};

	/**
	 * add device 하는 중 device 임시 저장
	 * @memberof Devices
	 * @param {Object} data device data
	 */
	this.setCurrentDevice = function(device) {
		this.currentDevice = device;
	};

	/**
	 * add device 하는 중 임시 device 데이터 얻기
	 * @memberof Devices
	 * @returns {Object}
	 */
	this.getCurrentDevice = function() {
		return this.currentDevice;
	};

	this.setMenuBtnPages = function(pages) {
		this.menuBtnPages = pages;
	};

	this.getMenuBtnPages = function() {
		return this.menuBtnPages;
	};

	this.setHardBtnPages = function(pages) {
		this.hardBtnPages = pages;
	};

	this.getHardBtnPages = function() {
		return this.hardBtnPages;
	};

	// function 들 array 초기화
	this.initFunctions = function() {
		 this.functions = [];
	};

	this.setFunctions = function(id, funcs) {

		for(var index = 0; index < this.functions.length; index++) {
			if(this.functions[String(id)] !== undefined) {
				this.functions[String(id)] = angular.copy(funcs);
				return;
			}
		}

		this.functions[String(id)] = angular.copy(funcs);
	};

	this.getFunctions = function(id) {
		if(this.functions[String(id)] !== undefined) {
			return this.functions[String(id)];
		}
		return null;
	};


	/**
	 * 해당 device 의 connected device(즉, command 목록) 얻기
	 * @memberof Devices
	 * @param {Number} roomId room ID
	 * @param {Number} deviceId device ID
	 * @returns {Promise} Future object
	 */
	this.fetchFunctions = function(roomId, deviceId) {
		var d = $q.defer();

		var url;
		if ($rootScope.virtualEditor) {
			url = '/api/dealer/device/get_con_dev/' + roomId + '/' + deviceId;
		} else {
			url = '/api/device/get_con_dev/' + roomId + '/' + deviceId;
		}

		// 해당 device 의 connected device(즉, command 목록) 얻기 API 호출
		$http.post(url).success(function (response) {
			if (response.result) {
				d.resolve(response.data);
			} else {
				d.reject(response.error);
			}
		}).error(function(error) {
			d.reject(error);
		});
		return d.promise;
	};

	/**
	 * punch 정보 (punch한 Device의 ID) 얻기
	 * @memberof Devices
	 * @param {Number} roomId room ID
	 * @param {Number} deviceId device ID
	 * @returns {Promise} Future object
	 */
	this.fetchPunchDevice = function(roomId, deviceId) {

		var d = $q.defer();

		var url;
		if ($rootScope.virtualEditor) {
			url = '/api/dealer/device/get_punch/' + roomId + '/' + deviceId;
		} else {
			url = '/api/device/get_punch/' + roomId + '/' + deviceId;
		}

		// punch 정보 (punch한 Device의 ID) 얻기 API 호출
		$http.post(url).success(function (response) {
			if (response.result) {
				d.resolve(response.data);
			} else {
				d.reject(response.error);
			}
		}).error(function(error) {
			d.reject(error);
		});
		return d.promise;
		
	};

	/**
	 * device 생성
	 * @memberof Devices
	 * @param {Number} roomId room ID
	 * @param {String} data device 정보 json string
	 * @returns {Promise} Future object
	 */
	this.createOne = function(roomId, data) {
		var d = $q.defer();

		var url;
		if ($rootScope.virtualEditor) {
			url = '/api/dealer/device/create/' + roomId;
		} else {
			url = '/api/device/create/' + roomId;
		}

		// device 생성 API 호출
		$http.post(url, data).success(function (response) {
			if (response.result) {
				d.resolve(response);
			} else {
				d.reject(response.error);
			}
		}).error(function (error) {
			d.reject(error);
		});
		return d.promise;
	};

	/**
	 * learn device 생성
	 * @memberof Devices
	 * @param {Number} roomId room ID
	 * @param {String} data device 정보 json string
	 * @returns {Promise} Future object
	 */
	this.createCustomOne = function(roomId, data) {
		var d = $q.defer();

		var url;
		if ($rootScope.virtualEditor) {
			url = '/api/dealer/device/create_custom/' + roomId;
		} else {
			url = '/api/device/create_custom/' + roomId;
		}

		// learn device 생성 API 호출
		$http.post(url, data).success(function (response) {
			if (response.result) {
				d.resolve(response);
			} else {
				d.reject(response.error);
			}
		}).error(function (error) {
			d.reject(error);
		});
		return d.promise;
	};

	this.makeBlankMenuButton = function(btnId, pgBtnIdx, props ) {
		return {  id: btnId, 
							page_btn_idx: pgBtnIdx, 
							display_text: null, 
							repeat_min: props.repeat.min, 
							repeat_macro: props.repeat.macro, 
							repeatSetting: 'default',
							room_id: props.room_id,
							device_id: props.device_id ? props.device_id : -1,
							activity: '',
							auto_wait: 0,
							edit_type: 1,
							func: null,
							hidden_option: 0,
							image_name: '',
							link_id: -1,
							macro: '',     
							popup: 0,
							press_hold: true };
	};     


	this.makeBlankMenuPage = function(props) {
		var pg = { id:0, btns: [] };

		for (var i=0, j=8192; i < 6; i++, j++) {
			pg.btns.push({  id: j,
											page_btn_idx: i,
											display_text: null, 
											repeat_min: props.repeat.min,
											repeat_macro: props.repeat.macro,
											repeatSetting: 'default',
											room_id: props.room_id,
											device_id: props.device_id ? props.device_id : -1,  
											activity: '',
											auto_wait: 0,
											edit_type: 1,
											func: null,
											hidden_option: 0,
											image_name: '',
											link_id: -1,
											macro: '',     
											popup: 0,
											press_hold: true });
		}

		console.log(pg);
		return pg;
	};

	this.setBtnDefaults = function(button) {
		if (!button.hasOwnProperty('activity')) { button.activity = ''; }
		if (!button.hasOwnProperty('auto_wait')) { button.auto_wait = 0; }
		if (!button.hasOwnProperty('edit_type')) { button.edit_type = 1; }
		if (!button.hasOwnProperty('func')) { button.func = null; }
		if (!button.hasOwnProperty('hidden_option')) { button.hidden_option = 0; }
		if (!button.hasOwnProperty('image_name')) { button.image_name = ''; }
		if (!button.hasOwnProperty('macro')) { button.macro = ''; }
		if (!button.hasOwnProperty('link_id')) { button.link_id = -1; }
		if (!button.hasOwnProperty('popup')) { button.popup = 0; }
		if (!button.hasOwnProperty('press_hold')) { button.press_hold = true; }
	};

	this.addHardBtnProps = function (props) {
		var self = this;
		_.forEach(self.hardBtnPages, function(hardBtnPage) {
			_.forEach(hardBtnPage.btns, function(btn) {

				if (!btn.hasOwnProperty('display_text')) {
					btn.display_text = null;
					btn.repeat_min = props.repeat.min;
					btn.repeat_macro = props.repeat.macro;
					btn.repeatSetting = 'default';
					btn.device_id = props.device_id;
					btn.room_id = props.room_id;
					self.setBtnDefaults(btn);
				}
			});
		});
	};

	// device 정보 얻기
	this.getOne = function(roomId, deviceId) {
		var deviceProps,
				self = this,
				d = $q.defer();
		var aliasDevices = [];

		
		function assignBtnFields(btn, macro, props) {

			if ( macro.hasOwnProperty('repeat_macro') && macro.hasOwnProperty('repeat_min') ) {
				_.assign(btn, { repeat_min: macro.repeat_min,
												repeat_macro: macro.repeat_macro,
												repeatSetting:'custom' });
			} else {
				_.assign(btn, { repeat_min: props.repeat.min,
												repeat_macro: props.repeat.macro,
												repeatSetting:'default' });
			}

			btn.func = _.where(props.dbCon, {'id': macro.func})[0]; 

			//console.log('press_hold', macro.press_hold);
			
			if (macro.hasOwnProperty('press_hold')) {
				btn.press_hold = macro.press_hold ? true:false;
			} else {
				btn.press_hold = btn.func.press_hold ? true:false;
			}

			if (btn.hasOwnProperty('hidden')) {
				btn.hidden = btn.hidden ? true:false;
			} else {
				btn.hidden = false;
			}

		}

		var url;
		if ($rootScope.virtualEditor) {
			url = '/api/dealer/device/get/' + roomId + '/' + deviceId;
		} else {
			url = '/api/device/get/' + roomId + '/' + deviceId;
		}

		// 해당 device 얻기 API 호출
		$http.post(url)
		.success(function(response) {
			console.log('response=', response);
			if (response.result) {
				self.menuBtnPages = [];
				self.initHardBtnPages();

				deviceProps = _.omit(response.data, 'pages');

				if (response.data.pages.length=== 0) {
					self.menuBtnPages.push( self.makeBlankMenuPage(deviceProps) );
					self.addHardBtnProps(deviceProps);
				} else {          
					if (response.data.pages.length === 1 && response.data.pages[0].id === -1) {
						console.log('1 page and its a hardBtnPage');
						self.menuBtnPages.push( self.makeBlankMenuPage(deviceProps) );
					}

					_.forEach(response.data.pages, function(page) {
						var pgToAdd = { btns: [] },
								btnIds;

						if (page.page_hidden) {
							pgToAdd.page_hidden = page.page_hidden;
						} else {
							pgToAdd.page_hidden = 0;
						}

						for (var i=0; i < 6; i++) {
							pgToAdd.btns.push({ page_btn_idx: i, display_text: null });
						}

						// Hard button manipulation

						if (page.id === -1) {
							_.forEach(page.btns, function(btn) {
								_.forEach(self.hardBtnPages, function(hardBtnPage) {
									_.forEach(hardBtnPage.btns, function(button) {
										if (button.id === btn.id) {
											var macro = JSON.parse(btn.macro)[0];

											_.assign(button, btn);

											if(macro.type == 6 && deviceId != macro.device_id) {
												var aliasDeviceProps = null;
												aliasDeviceProps = _.where(aliasDevices, {'id': macro.device_id})[0]; 
												if(aliasDeviceProps) {
														//console.log('exist aliasDeviceProps=', aliasDeviceProps);
														assignBtnFields(button, macro, aliasDeviceProps);
												} else {
													self.getDeviceData(roomId, macro.device_id).then(function(data) {
														aliasDeviceProps = data;
														//console.log('aliasDeviceProps=', aliasDeviceProps);
														aliasDevices.push(aliasDeviceProps);
														assignBtnFields(button, macro, aliasDeviceProps);
													}).catch();
												}
											} else {
												assignBtnFields(button, macro, deviceProps);
											}
											
										}
									});
								});
							});

							return;
						}

						pgToAdd.id = page.id;

						// Menu page button manipulation

						_.forEach(page.btns, function(btn) {
							var macro = JSON.parse(btn.macro)[0],
									newBtn = _.clone(btn);

							if(macro.type == 6 && deviceId != macro.device_id) {
								var aliasDeviceProps = null;
								//console.log('aliasDevices=', aliasDevices);
								aliasDeviceProps = _.where(aliasDevices, {'id': macro.device_id})[0]; 
								if(aliasDeviceProps) {
										//console.log('exist aliasDeviceProps=', aliasDeviceProps);
										assignBtnFields(newBtn, macro, aliasDeviceProps);
								} else {
									self.getDeviceData(roomId, macro.device_id).then(function(data) {
										aliasDeviceProps = data;
										//console.log('aliasDeviceProps=', aliasDeviceProps);
										aliasDevices.push(aliasDeviceProps);
										assignBtnFields(newBtn, macro, aliasDeviceProps);
									}).catch();
								}
							} else {
								assignBtnFields(newBtn, macro, deviceProps);
							}

							///사용하기 편하도록 object type으로 변환.
							newBtn.macro = JSON.parse(newBtn.macro);

							pgToAdd.btns.splice(newBtn.page_btn_idx,1,newBtn);
						});

						// Filling in the rest of the page

						btnIds = _(pgToAdd.btns).pluck('id').value();
						//console.log('btnIds=', btnIds);
						if(btnIds.filter(Number).length < 6) {

							//Mathematical equation to get the correct starting id of the page to be added
							var min = 8192 + (pgToAdd.id * 6),
								btnId = min;
							//console.log('btnId=', btnId);

							for (var idx = 0; idx < 6; idx++) {
								var button = pgToAdd.btns[idx];
								button.id = btnId;
								//if there is no repeat setting on the btn then add the default
								if ( !button.hasOwnProperty('repeatSetting') ) {
									button.repeat_min = deviceProps.repeat.min;
									button.repeat_macro = deviceProps.repeat.macro;
									button.repeatSetting = 'default';
								}
								if (!button.hasOwnProperty('room_id')) { button.room_id = roomId; }
								if (!button.hasOwnProperty('device_id')) { button.device_id = deviceId; }     
								
								self.setBtnDefaults(button);

								btnId++;
							}
						}

						self.menuBtnPages.push({ id: pgToAdd.id , btns: pgToAdd.btns, page_hidden: pgToAdd.page_hidden });
					});

					self.addHardBtnProps(deviceProps);
				}
				console.log('deviceProps=', deviceProps);
				console.log('hardBtnPages=', self.hardBtnPages);
				console.log('menuBtnPages=', self.menuBtnPages);

				d.resolve(deviceProps);
			} else {
				d.reject( response.error);
			}
		})
		.error(function(error) {
			alert('Please try again');
			d.reject(error);
		});
		return d.promise;

	};

	/**
	 * 해당 device 저장
	 * @memberof Devices
	 * @param {Number} roomId room ID
	 * @param {Number} deviceId device ID
	 * @param {String} data 해당 device 의 데이터 json string
	 * @returns {Promise} Future object
	 */
	this.storeOne = function(roomId, deviceId, data) {
		var d = $q.defer();

		var url;
		if ($rootScope.virtualEditor) {
			url = '/api/dealer/device/store/' + roomId + '/' + deviceId;
		} else {
			url = '/api/device/store/' + roomId + '/' + deviceId;
		}

		// 해당 device 저장 API 호출
		$http.post(url, data).success(function (response) {
			if (response.result) {
				d.resolve(response.result);
			} else {
				d.reject(response.error);
			}
		}).error(function (error) {
			d.reject(error);
		});
		return d.promise;
	};


	/**
	 * device data get
	 * @memberof Devices
	 * @param {Number} roomId room ID
	 * @param {Number} deviceId device ID
	 * @returns {Promise} Future object
	 */
	this.getDeviceData = function(roomId, deviceId) {
		var d = $q.defer();

		var url;
		if ($rootScope.virtualEditor) {
			url = '/api/dealer/device/get/' + roomId + '/' + deviceId;
		} else {
			url = '/api/device/get/' + roomId + '/' + deviceId;
		}
		
		// 해당 device 얻기 API 호출
		$http.post(url)
		.success(function(response) {
			console.log(response);
			if (response.result) {
				d.resolve(response.data);
			} else {
				d.reject( response.error);
			}
		})
		.error(function(error) {
			alert('Please try again');
			d.reject(error);
		});
		return d.promise;

	};

	/**
	 * twoway device 생성
	 * @memberof Devices
	 * @param {Number} roomId room ID
	 * @param {String} data device 정보 json string
	 * @returns {Promise} Future object
	 */
	this.createTwowayDevice = function(roomId, data) {
		var d = $q.defer();

		// device 생성 API 호출
		$http.post('/api/twoway_device/create/' + roomId, data).success(function (response) {
			if (response.result) {
				d.resolve(response);
			} else {
				d.reject(response.error);
			}
		}).error(function (error) {
			d.reject(error);
		});

		return d.promise;
	};

	/**
	 * twoway device update
	 * @memberof Devices
	 * @param {Number} roomId room ID
	 * @param {Number} deviceId device ID
	 * @returns {Promise} Future object
	 */
	this.updateTwowayDevice = function(roomId, deviceId) {
		var d = $q.defer();

		// 해당 device update API 호출
		$http.post('/api/twoway_device/update/' + roomId + '/' + deviceId)
			.success(function(response) {
				console.log(response);
				if (response.result) {
					d.resolve(response.data);
				} else {
					d.reject( response.error);
				}
			})
			.error(function(error) {
				d.reject(error);
			});
		return d.promise;

	};


});
