'use strict';
/**
 * @ngdoc overview
 * @name hcmEditorApp
 * @description
 * # hcmEditorApp
 *
 * Main module of the application.
 */

/*global app:true*/

var app = angular.module('hcmEditorApp', [
  'ngAnimate',
  'ngCookies',
  'ngSanitize',
  'ui.router',
  'ui.bootstrap',
  'ui.sortable',
  'ui.select',
  'mgcrea.ngStrap',
  'checklist-model',
  'vr.directives.slider',
  'angular-loading-bar',
  'ngFx',
  'toastr',
  'angular-jwt',
  'NgSwitchery'
]);

app.constant('VERSION', '0.0.5271a');

app.run( function ($rootScope, $state, $stateParams, VERSION, Auth) {

  $rootScope.version = VERSION;
  $rootScope.$state = $state;
  $rootScope.$stateParams = $stateParams;
  $rootScope.previousState = {};

  // $stateChangeSuccess 이벤트가 발생하면 $rootScope.previousState 에 이전 state 의 name 과 params 를 저장
  $rootScope.$on('$stateChangeSuccess',  function (event, toState, toParams, fromState, fromParams) {
    $rootScope.previousState.name = fromState.name;
    $rootScope.previousState.params = fromParams;
  });

  // $stateChangeStart 이벤트가 발생하면 로그인한 사용자 정보를 가져오고 이동할 state 의 로그인 필요여부에 따른 처리를 수행
  $rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
    Auth.currentUser().then(function(user) {

      if (!toState.auth) {  // 이동할 state 가 로그인이 필요없는 경우
        console.info('Route does not require authentication.');
      } else {  // 이동할 state 가 로그인이 필요한 경우
        console.info('Route requires authentication.');
      }

      if (user) { // 로그인 되어 있는 경우
        console.info('User is authenticated.');
      } else {  // 로그인 되어 있지 않은 경우
        console.error('User is not authenticated.');
      }

      if (fromState.auth && !toState.auth && user) {  // 로그인 되어 있으면서 로그인 필요 state -> 불필요 state 로 이동
        console.warn('Going from Auth route to non Auth route');
        //event.preventDefault();
      } else if (toState.auth && !user) {   // 로그인 필요 state 로 이동하면서 로그인 되어 있지 않은 경우
        console.error('Routing back to Login page.');
        $state.go('login', {e: 401});   // e=401 파라미터를 가지고 로그인 페이지로 이동
        //event.preventDefault();
      } else if (toState.auth && user) {  // 로그인 필요 state 로 이동하면서 로그인 되어 있는 경우
        //console.info('Route requires authentication and user is authenticated.');
      }
    });
  });


});

/**
 * @ngdoc service
 * @name authInterceptor
 * @description
 *  로그인을 하면 서버로 부터 token 을 받고 이를 로그인 사용자 정보에 저장하고 있습니다.
 *  로그인 후 사용할 수 있는 모든 기능들은 서버에 ajax 요청을 할 때 HTTP Header 에 이 token 을 보내줘야 합니다.
 *  authInterceptor 가 HTTP Header 에 Authorization: Bearer {token} 형태로 넣는 역할을 합니다.
 */
app.factory('authInterceptor', function ($rootScope, $q, $injector) {
  return {
    request: function(req) {
      var d = $q.defer();
      $injector.get('Auth').currentUser().then(function(user) {
        if(user) {
          req.headers.Authorization = 'Bearer ' + user.token;
          d.resolve(req);
        } else {
          d.resolve(req);
        }
      });
      return d.promise;
    },
    responseError: function (response) {
      if (response.status === 401) {
        $injector.get('User').logout();
        $injector.get('$state').go('login', {e: '401'});
        return $q.reject(response);
      } else {
        return $q.reject(response);
      }
    }
  };
});

// $httpProvider 의 interceptors 에 authInterceptor 를 추가해서 HTTP request 를 할 때 (ajax 요청할 때) authInterceptor 가 실행되게 함
app.config(function($httpProvider) {
  $httpProvider.interceptors.push('authInterceptor');
});

alert(navigator.userAgent);
// angular-ui ui-router 를 사용한 state, URL 설정
app.config(function($stateProvider, $urlRouterProvider, $locationProvider) {

// For any unmatched url, redirect to /state1
// 이하 코드에서 설정하지 않은 URL 의 경우 '/' 로 redirect 시킴
  $urlRouterProvider.otherwise('/');

// use the HTML5 History API : 이 옵션을 사용하면 주소창에 # 이 생기지 않습니다.
//$locationProvider.html5Mode(true);

// Now set up the states
// state 설정 시작
// state 설정의 옵션 property 중 auth 는 로그인이 필요한 state 인지 아닌지를 구분
  $stateProvider
    // 제일 첫 번째 페이지를 나타내는 url ('/') 에 대한 state 정의. [참고] state 이름 (home) 과 url ('/') 는 일치하지 않아도 됩니다.
    .state('home', {
      auth: false,
      url: '/',
      template: '<div class="editor-container" >' +
      '<div class="menu container">' +
      '<a class="btn btn-lg btn-menu btn-block" ui-sref="register">Register a new system here</a>' +
      '<a class="btn btn-lg btn-menu btn-block" ui-sref="login">Login to existing system</a>' +
      '</div></div>',
      controller: function($state, Auth) {
        // 로그인 되어 있으면 system-overview 페이지로 이동
        Auth.currentUser().then(function(user) {
          if(user) {
            $state.go('menu.system-overview');
          }
        });
      }
    })

    // 로그인
    .state('login', {
      auth: false,
      url: '/login?e',
      templateUrl: 'views/login.html',
      controller: 'LoginController'
    })

    // base station 이 offline 인 상태에서 "Forgot your password?" 링크를 클릭해서 password reset 을 한 다음 로그인 한 경우
    .state('ignore-offline-systems', {
      auth: false,
      url: '/ignore-offline-systems',
      templateUrl: 'views/ignore-offline-systems.html',
      controller: 'IgnoreOfflineController'
    })

    // base station 이 offline 인 상태에서 "Forgot your password?" 링크를 클릭해서 password reset 을 한 다음 새 시스템을 등록하러 온 경우
    .state('ignore-offline-systems-for-create', {
      auth: false,
      url: '/ignore-offline-systems',
      templateUrl: 'views/ignore-offline-systems.html',
      controller: 'IgnoreOfflineCreateController'
    })

    // reset password
    .state('forgot', {
      auth: false,
      url: '/forgot',
      templateUrl: 'views/forgot-password.html',
      controller: 'ForgotController'
    })

    // 새로운 system 생성
    .state('register', {
      auth: false,
      url: '/register',
      templateUrl: 'views/register.html',
      controller: 'RegisterController',
      resolve: {
        availableModels: function($q, Registration) {
          var d = $q.defer();

          // base station 의 type 들을 얻기
          Registration.getModelTypes().then(
            function(response) {
              if(response.data.result) {
                console.log('Loaded from resolve!');
                console.log(response.data.data);
                d.resolve(JSON.parse(response.data.data));
              } else {
                d.reject();
              }
            },
            function(error) {
              alert('Please try again');
            }
          );
          return d.promise;
        }
      }
    })

    // register 과정 중 사용자에게 temporary password 를 이메일로 발송
    .state('send-email', {
      auth: false,
      url: '/send-email',
      templateUrl: 'views/send-email.html',
      controller: 'SendEmailController'
    })

    // register 과정 중 새로운 사용자 등록
    .state('add-user', {
      auth: false,
      url: '/add-user',
      templateUrl: 'views/add-user.html',
      controller: 'AddUserController'
    })

    // register 과정 중 새로운 system 등록
    .state('add-new-system', {
      auth: true,
      url: '/add-new-system',
      templateUrl: 'views/add-new-system.html',
      controller: 'AddNewSystemController',
      resolve: {
        // 이전 과정에서 등록된 새로운 사용자 정보
        currentUser: function (Auth) {
          return Auth.currentUser();
        },
        // timezone 목록 얻기
        timeZones: function($q, Timezones) {
          var d = $q.defer();

          Timezones.getAll().then(function(data) {
            d.resolve(data);
          }).catch(function(error) {
            d.reject(error);
          });

          return d.promise;
        }
      }
    })

    // system 선택 : 로그인 후, 새로운 system 등록 성공 후, system 삭제 성공 후에 여기로 이동함
    .state('system-select', {
      auth: true,
      url: '/system-select',
      templateUrl: 'views/system-select.html',
      controller: 'SystemSelectController',
      resolve: {
        resolvedSystems: function(Systems) {
          return Systems.fetch();
        }
      }
    })

    // ********************************************************
    // Recovery Base station
    // ********************************************************

    // 로그인 했는데 base station 이 없는 경우 : 다른 사람이 내 base station 을 등록한 경우
    .state('recovery-bstation', {
      auth: true,
      url: '/recovery-bstation',
      template: '<div ui-view></div>',
      controller: function($state) {
        $state.go('recovery-bstation.select');
      }
    })

    // 이 상황에 대한 안내문구 표시. Next 버튼을 클릭하면 enter-key state 로 이동
    .state('recovery-bstation.select', {
      auth: true,
      url: '?rooms',
      templateUrl: 'views/recovery-bstation.html',
      controller: function($scope, $state, $stateParams, User) {
        $scope.$parent.rooms = angular.fromJson($stateParams.rooms);

        $scope.logout = function() {
          User.logout();
          $state.go('login');
        };

        $scope.doNext = function() {
          $state.go('recovery-bstation.enter-key');
        };
      }
    })

    // Programming Key 입력
    .state('recovery-bstation.enter-key', {
      auth: true,
      url: '/enter-key',
      templateUrl: 'views/recovery-bstation-key.html',
      controller: function($scope, $state, toastr, availableModels, Registration, Auth, User, Systems) {
        $scope.register = {
          modelType: 'HCM-C1'
        };
        $scope.availableModels = availableModels;

        $scope.goBack = function() {
          $state.go('recovery-bstation.select');
        };

        $scope.doNext = function() {
          var key = $scope.register.key.first + $scope.register.key.second + $scope.register.key.third + $scope.register.key.fourth,
            key = key.toUpperCase(),
            type = $scope.register.modelType;

          $scope.$parent.key = key;
          $scope.$parent.type = type;

          var jsonData = JSON.stringify({ modelType: type, key: key});

          Systems.checkKey(jsonData).then(function(data) {
            $state.go('recovery-bstation.room-select', {mac: data.mac});
          })
            .catch(function(error) {
              alert(error);
            });
        };
      },
      resolve: {
        availableModels: function($q, Registration) {
          var d = $q.defer();

          // base station 의 type 들을 얻기
          Registration.getModelTypes().then(
            function(response) {
              if(response.data.result) {
                console.log('Loaded from resolve!');
                console.log(response.data.data);
                d.resolve(JSON.parse(response.data.data));
              } else {
                d.reject();
              }
            },
            function(error) {
              alert('Please try again');
            }
          );
          return d.promise;
        }
      }
    })

    // room 선택
    .state('recovery-bstation.room-select', {
      auth: true,
      url: '/room-select?mac',
      templateUrl: 'views/recovery-bstation-room.html',
      controller: function($scope, $state, $stateParams, User, Systems) {
        $scope.rooms = $scope.$parent.rooms;
        $scope.mac = $stateParams.mac;

        if (!$scope.rooms || !$scope.rooms.length) {
          User.logout();
          $state.go('login');
          return;
        }

        $scope.assignMaster = {
          modelType: $scope.$parent.type,
          key: $scope.$parent.key,
          roomId: $scope.rooms[0].id
        };

        $scope.goBack = function() {
          $state.go('recovery-bstation.enter-key');
        };

        // Next 버튼 클릭하면 나오는 팝업에서 Yes 선택하면 실행됨
        // base station 설정
        $scope.replace = function() {
          var assignMaster = function(json) {
            return Systems.assignMaster(json).then(function(data) {
              return Systems.getCurrentSystem().id;
            });
          };

          var updateSystem = function(id) {
            return Systems.updateSystem(id).then(function (data) {
              return $state.go('recovery-bstation.download');
            });
          };

          assignMaster(JSON.stringify($scope.assignMaster))
            .then(updateSystem)
            .catch(function (error) {
              alert(error);
            });
        };
      }
    })

    // base station 설정 완료 후 나오는 화면. 다운로드 또는 system-overview 로 이동하는 버튼 표시
    .state('recovery-bstation.download', {
      auth: true,
      url: '/download',
      templateUrl: 'views/recovery-bstation-download.html',
      controller: function($scope, $state) {
        $scope.download = function() {
          $state.go('menu.download');
        };

        $scope.later = function() {
          $state.go('menu.system-overview');
        };
      }
    })

    // ********************************************************
    // menu state 설정 시작
    // ********************************************************

    // 상단 메뉴를 클릭해서 나오는 모든 기능은 이 state 의 nested state 입니다.
    .state('menu', {
      auth: true,
      abstract: true,
      url: '/menu',
      // 상단 메뉴와 메뉴의 내용이 나오는 컨테이너 템플릿
      template: '<tabset justified="true">' +
      '<tab ng-repeat="t in tabs"  select="go(t.route)" active="t.active"><tab-heading ng-bind-html="t.heading"></tab-heading></tab>' +
      '</tabset><div class="editor-container" ui-view></div>',
      controller: function($scope, $state, $sanitize, $modal, currentSystem, currentUser, Systems) {
        if (currentUser.optMenuShow) {
          $scope.tabs = [
            { heading: $sanitize('<i class="fa fa-laptop tab-icon"></i><span class="tab-title">Programming Menu</span>'), route:'menu.programming.options', index:"menu.programming.**", active:false },
            { heading: $sanitize('<i class="fa fa-wrench tab-icon"></i><span class="tab-title">Advanced Menu</span>'), route:'menu.advanced.options', index:'menu.advanced.**', active:false },
            { heading: $sanitize('<i class="fa fa-globe tab-icon"></i><span class="tab-title">Home Overview</span>'), route:'menu.system-overview', index:'menu.system-overview.**', active:false },
            { heading: $sanitize('<i class="fa fa-download tab-icon"></i><span class="tab-title">Download</span>'), route:'menu.download', index:'menu.download.**', active:false }
          ];
        } else {
          $scope.tabs = [
            { heading: $sanitize('<i class="fa fa-laptop tab-icon"></i><span class="tab-title">Programming Menu</span>'), route:'menu.programming.options', index:"menu.programming.**", active:false },
            { heading: $sanitize('<i class="fa fa-globe tab-icon"></i><span class="tab-title">Home Overview</span>'), route:'menu.system-overview', index:'menu.system-overview.**', active:false },
            { heading: $sanitize('<i class="fa fa-download tab-icon"></i><span class="tab-title">Download</span>'), route:'menu.download', index:'menu.download.**', active:false }
          ];
        }

        $scope.go = function(route){
          $state.go(route);
        };

        $scope.active = function(route){
          return $state.includes(route);
        };

        $scope.$on('$stateChangeSuccess', function() {
          $scope.tabs.forEach(function(tab) {
            tab.active = $scope.active(tab.index);
          });
        });

        $scope.system = currentSystem;

        $scope.optHelpShow = currentUser.optHelpShow;

        $scope.showHelpModal = function(menu) {
          switch (menu) {
            case 'add-remote':
              $scope.helpTitle = 'Add a remote to the room';
              break;

            case 'add-device':
              $scope.helpTitle = 'Add Entertainment devices to the system';
              break;

            case 'volume-control':
              $scope.helpTitle = 'Setup volume control for devices';
              break;

            case 'power-off':
              $scope.helpTitle = 'Setup the Power Off button';
              break;

            case 'activities':
              $scope.helpTitle = 'Setup a simple activity for a device';
              break;

            case 'add-controller':
              $scope.helpTitle = 'Add an additional controller';
              break;

            case 'switch-rooms':
              $scope.helpTitle = 'Program a different room';
              break;

            case 'add-automated-activities':
              $scope.helpTitle = 'Automate activities on the Entertainment Menu';
              break;

            case 'edit-automated-activities':
              $scope.helpTitle = 'Edit your automated activities';
              break;

            case 'add-room':
              $scope.helpTitle = 'Add a room to the system';
              break;

            case 'edit-entertainment-menu':
              $scope.helpTitle = 'Edit the Entertainment Menu';
              break;

            case 'device-layout':
              $scope.helpTitle = 'Edit a device\'s layout';
              break;

            case 'learn-ir':
              $scope.helpTitle = 'Learn codes from an IR remote';
              break;

            case 'automated-activity-type':
              $scope.helpTitle = 'What type of automated activity do you want?';
              break;

            case 'edit-automated-activities-select-button':
              $scope.helpTitle = 'Select a button or device to edit its automated activity';
              break;

            case 'edit-entertainment-menu-edit-layout':
              $scope.helpTitle = 'Edit the layout of the remote\'s entertainment main screen';
              break;

            case 'device-layout-edit':
              $scope.helpTitle = 'Edit the layout of the device\'s buttons';
              break;
          }

          Systems.getHelpContent(menu).then(function(response) {
            $scope.helpContent = response;

            var modal = $modal({
              scope: $scope,
              template: 'views/modal-tpls/programming-help.html',
              container: 'body',
              show: false
            });
            modal.$promise.then(modal.show);
          }, function(error) {
            toastr.error(error);
          });
        };

      },
      resolve: {
        // 현재 선택된 system 가져오기
        currentSystem: function($q, $window, Systems) {
          var d = $q.defer();
          if (Systems.getCurrentSystem()) {
            console.log('in resolve');
            d.resolve(Systems.getCurrentSystem());
          } else {
            var user = JSON.parse($window.localStorage.getItem('hcm_editor'));
            Systems.updateSystem(user.system_id).then(function(data) {
              d.resolve(Systems.getCurrentSystem());
            }).catch(function(error) {
              d.reject(error);
            });
          }
          return d.promise;
        },
        // 로그인한 사용자 정보 가져오기
        currentUser: function (Auth) {
          return Auth.currentUser();
        }
      }
    })

    // ********************************************************
    // Programming Menu
    // ********************************************************

    .state('menu.programming', {
      auth: true,
      abstract: true,
      url: '/programming',
      template: '<div ui-view></div>',
      controller: function ($scope, $state, Systems) {
        var id = Systems.getCurrentRoom();

        $scope.system = Systems.getCurrentSystem();

        if (id === null) {  // 현재 room 이 없으면 system 의 첫 번째 room 을 현재 room 으로 설정
          $scope.room = $scope.system.rooms[0];
          Systems.setCurrentRoom($scope.room.id);
        } else {
          $scope.room = _.find($scope.system.rooms, {'id': id});
        }

        if ($scope.system.rooms.length === 1) {
          $scope.hasOneRoom = true;
        } else {
          $scope.hasOneRoom = false;
        }

        $scope.switchRoom = function(id) {
          Systems.setCurrentRoom(id);
          $scope.room = _.find($scope.system.rooms, {'id': id});
          $state.go('menu.programming.options');
        };
      }
    })

    // Programming 메뉴 첫 화면에 나오는 메뉴 목록
    .state('menu.programming.options', {
      auth: true,
      url: '',
      templateUrl: 'views/programming-options.html',
      controller: function($scope) {}
    })


    // ********************************************************
    // Programming Menu ---- Adding a device
    // ********************************************************

    .state('menu.programming.add-device', {
      auth: true,
      abstract: true,
      url: '/add-device',
      template: '<div ui-view></div>',
      controller: function($scope) {
        $scope.device = {};
        $scope.query = {};
      },
      resolve: {
        // device types 얻기
        categories: function($q, toastr, Database) {
          var d = $q.defer();
          Database.retreiveDeviceTypes().then(
            function(data) {
              d.resolve(data);
            },
            function(error) {
              toastr.error(error, 'Error');
              d.reject(error);
            }
          );
          return d.promise;
        }
      }
    })

    // device type 선택
    .state('menu.programming.add-device.device-type', {
      auth: true,
      url: '/type',
      templateUrl: 'views/add-devices/device-type.html',
      controller: 'DeviceTypeController'
    })

    // device name 입력
    .state('menu.programming.add-device.device-name', {
      auth: true,
      url: '/name',
      templateUrl: 'views/add-devices/device-name.html',
      controller: 'DeviceNameController'
    })

    // device brand 선택
    .state('menu.programming.add-device.device-brand', {
      auth: true,
      url: '/brand',
      templateUrl: 'views/add-devices/device-brand.html',
      controller: 'DeviceBrandController'
    })

    // device popular model 선택
    .state('menu.programming.add-device.device-model', {
      auth: true,
      url: '/model',
      templateUrl: 'views/add-devices/device-model.html',
      controller: 'DeviceModelController',
      resolve: {
        // popular 모델 얻기
        popularDevices: function($q, Database, Devices) {
          var device = Devices.getCurrentDevice(),
            d = $q.defer();

          if (device) {
            Database.searchPopularModels(device.type.name, device.brand.name)
              .then(function(devices) {
                d.resolve(devices);
              })
              .catch(function(error) {
                d.reject(error);
                toastr.error(error, 'Error');
              });
          } else {
            d.resolve({});
          }

          return d.promise;
        }
      }
    })

    // device model 검색
    .state('menu.programming.add-device.device-model-search', {
      auth: true,
      url: '/model-search',
      templateUrl: 'views/add-devices/device-model-search.html',
      controller: 'DeviceModelSearchController'
    })

    // device 정보 설정 후 생성
    .state('menu.programming.add-device.device-settings', {
      auth: true,
      url: '/settings',
      templateUrl: 'views/add-devices/device-settings.html',
      controller: 'DeviceSettingsController'
    })

    // favorite channels 설정
    .state('menu.programming.add-device.favchannels-option', {
      auth: true,
      url: '/favorite-channels',
      templateUrl: 'views/add-devices/favchannels-option.html',
      controller: 'FavChannelsOptionController'
    })

    // ********************************************************
    // Programming Menu ---- Add a base station
    // ********************************************************

    .state('menu.programming.add-controller', {
      auth: true,
      abstract: true,
      url: '/add-controller',
      template: '<div ui-view></div>',
      controller: function($scope) {
        $scope.addBaseStation = {selection: null, displayText: null };
      },
      resolve: {
        // base station 검색 결과 목록
        searchResults: function ($q, toastr, Systems) {
          var d = $q.defer();
          // deviceName 에 hcm-c1 이 포함되어 있는 경우 base station 찾기
          Systems.searchHardware(true, 'hcm-c1').then(
            function(data) {
              console.log(data);
              d.resolve(data);
            },
            function (error) {
              if (error.match('NO DEVICE')) {
                d.resolve({});
              } else {
                toastr.error(error);
                d.reject(error);
              }
            }
          );
          return d.promise;
        }
      }
    })

    // base station 검색결과 목록 표시
    .state('menu.programming.add-controller.select', {
      auth: true,
      url: '',
      templateUrl: 'views/add-controllers/select-controller.html',
      controller: 'SelectBaseController'
    })

    // ********************************************************
    // Programming Menu ---- Add a remote
    // ********************************************************

    .state('menu.programming.add-remote', {
      auth: true,
      url: '/add-remote',
      template: '<div ui-view></div>',
      controller: function($scope) {
        $scope.addRemote = {'selection': null, 'room': $scope.room};
      },
      resolve: {
        // remote 검색 결과 목록
        searchResults: function ($state, $q, toastr, Systems) {
          var d = $q.defer();
          // deviceName 에 hcm-r1 이 포함되어 있는 경우 remote 찾기
          Systems.searchHardware(true, 'hcm-r1').then(
            function(data) {
              console.log(data);
              d.resolve(data);
            },
            function (error) {
              if (error.match('NO DEVICE')) {
                d.resolve({});
              } else {
                toastr.error(error);
                d.reject(error);
              }
            }
          );
          return d.promise;
        }
      }
    })

    // remote 검색결과 목록 표시
    .state('menu.programming.add-remote.select', {
      auth: true,
      url: '',
      templateUrl: 'views/add-remotes/select-remote.html',
      controller: 'SelectRemoteController'
    })

    // ********************************************************
    // Programming Menu ---- Build a simple activity
    // ********************************************************
    .state('menu.programming.activities', {
      auth: true,
      abstract: true,
      url: '/activities',
      template: '<div ui-view=""></div>',
      controller: 'ActivitiesController'
    })

    // based on device 선택 화면
    .state('menu.programming.activities.choose-device', {
      auth: true,
      url: '/choose-device',
      templateUrl: 'views/activities/choose-device.html',
      controller: 'ChooseActivityDeviceController'
    })

    // simple activity 선택 화면
    .state('menu.programming.activities.devices-to-use', {
      auth: true,
      url: '/devices-to-use',
      templateUrl: 'views/activities/devices-to-use.html',
      controller: 'ActivityDevicesController'
    })

    // command 선택 화면
    .state('menu.programming.activities.commands', {
      auth: true,
      url: '/commands',
      templateUrl: 'views/activities/commands.html',
      controller: 'ActivityDeviceCommandsController'

    })

    // ********************************************************
    // Programming Menu ---- Setting volume punch through
    // ********************************************************
    .state('menu.programming.volume-control', {
      auth: true,
      abstract: true,
      url: '/volume-control/:roomId',
      template: '<div ui-view=""></div>',
      controller: function($scope, deviceId) {
        console.log(deviceId);
        $scope.volumeControl = {};
        $scope.volumeControl.punchFrom = null;
        $scope.volumeControl.punchTo = null;
        $scope.volumeControl.devices = {};

        var dest = angular.copy($scope.room.devices);
        dest.push({id: 0, name: 'Entertainment / Home Menu', punch_vol: deviceId});
        $scope.volumeControl.devices.destination = dest;

        var source = angular.copy($scope.room.devices);
        source.push({id: -1, name: 'None', punch_vol: -1});
        $scope.volumeControl.devices.source = source;
      },
      resolve: {
        // punch 정보 (punch한 Device의 ID)
        deviceId: function($stateParams, Devices) {
          return Devices.fetchPunchDevice($stateParams.roomId, 0);
        }
      }
    })

    // punch to device 선택 화면
    .state('menu.programming.volume-control.punch-to-device', {
      auth: true,
      url: '/punch-to-device',
      templateUrl: 'views/volume-control/punch-to-device.html',
      controller: 'PunchToDeviceController'
    })

    // punch from device 선택 화면
    .state('menu.programming.volume-control.punch-from-device', {
      auth: true,
      url: '/punch-from-device',
      templateUrl: 'views/volume-control/punch-from-device.html',
      controller: 'PunchFromDeviceController'
    })

    // ********************************************************
    // Programming Menu ---- Setting power off
    // ********************************************************

    .state('menu.programming.power-off', {
      auth: true,
      abstract: true,
      url: '/power-off',
      template: '<div ui-view=""></div>',
      controller: 'PowerOffController',
      resolve: {
        // room 정보 얻기
        room: function($q, $window, Systems) {
          var d = $q.defer();

          Systems.updateSystem(Systems.getCurrentSystem().id).then(function(data) {
            var room = _.find(Systems.getCurrentSystem().rooms, {'id': Systems.getCurrentRoom()});
            d.resolve(room);
          }).catch(function(error) {
            d.reject(error);
          });

          return d.promise;
        }
      }
    })

    // device 선택 화면
    .state('menu.programming.power-off.devices-to-use', {
      auth: true,
      url: '/devices-to-use',
      templateUrl: 'views/power-off/devices-to-use.html',
      controller: 'PowerOffDevicesController',
      resolve: {
        // button 의 정보 얻기
        currentMacro: function ($q, Systems) {
          var d = $q.defer();

          // 해당 room 의 power macro 데이터 얻어와서 저장
          Systems.updateCurrentMacroForPower(Systems.getCurrentRoom()).then(
            function(data) {
              console.log(data);
              d.resolve(data);
            },
            function (error) {
              alert(error);
              d.reject(error);
            }
          );
          return d.promise;
        }
      }
    })

    // command 선택 화면
    .state('menu.programming.power-off.commands', {
      auth: true,
      url: '/commands',
      templateUrl: 'views/power-off/commands.html',
      controller: 'PowerOffDeviceCommandsController'
    })


    // ********************************************************
    // Programming Menu ---- Switching rooms
    // ********************************************************

    .state('menu.programming.switch-rooms', {
      auth: true,
      url: '/switch-rooms',
      templateUrl: 'views/switch-rooms.html',
      controller: function($scope) {
        var roomId = angular.copy($scope.room.id);

        $scope.switchData = {'roomId': roomId };

      }
    })


    // ********************************************************
    // Advanced Menu
    // ********************************************************

    .state('menu.advanced', {
      auth: true,
      abstract: true,
      url: '/advanced',
      template: '<div ui-view></div>',
      controller: function($scope, Systems) {
        $scope.system = Systems.getCurrentSystem();
      }
    })

    // Advanced 메뉴 첫 화면에 나오는 메뉴 목록
    .state('menu.advanced.options', {
      auth: true,
      url: '',
      templateUrl: 'views/advanced-options.html',
      controller: function($scope, Rooms) {
        if (!Rooms.getScheEventEdit()) {
          Rooms.setScheEventData(null);
        }
      }
    })

    // ********************************************************
    // Advanced Menu - Add a macro
    // ********************************************************

    .state('menu.advanced.add-macros', {
      auth: true,
      abstract: true,
      url: '/add-macros',
      template: '<div ui-view></div>',
      controller: function($scope, $state, $timeout, Rooms) {
        $scope.addMacro = {room: {}, steps: [], button: {}, disablePopup: false,
          doneScreen: {index: 0, devices: []}};
        $scope.macroType = {id : null};
        // macroType id
        // 0 - turn off all
        // 1 - device activity
        // 2 - custom
        // 3 - scheduled event
        $scope.scheduledEvent = {};

        var scheEventData = Rooms.getScheEventData();

        // scheduled event 를 수정하러 들어온 경우
        if (scheEventData) {
          $timeout(function() {
            Rooms.disableScheEventEdit();
            $state.go('menu.advanced.add-macros.finish');
          }, 0);
        }
      }
    })

    // room 선택 화면
    .state('menu.advanced.add-macros.choose-room', {
      auth: true,
      url: '/choose-room',
      templateUrl: 'views/add-macros/choose-room.html',
      controller: 'AddMacroRoomController'
    })

    // macro type 선택 화면
    .state('menu.advanced.add-macros.macro-type', {
      auth: true,
      url: '/macro-type',
      templateUrl: 'views/add-macros/macro-type.html',
      controller: 'MacroTypeController'
    })

    // entertainment page button 생성할 button name 입력 화면
    .state('menu.advanced.add-macros.button-name', {
      auth: true,
      url: '/button-name',
      templateUrl: 'views/add-macros/button-name.html',
      controller: 'ButtonNameController'
    })

    // entertainment page device 생성할 device 선택 화면
    .state('menu.advanced.add-macros.choose-device', {
      auth: true,
      url: '/choose-device',
      templateUrl: 'views/add-macros/choose-device.html',
      controller: 'ChooseMacroDeviceController'
    })

    // macro device, commands 입력
    .state('menu.advanced.add-macros.finish', {
      auth: true,
      url: '/finish',
      templateUrl: 'views/add-macros/edit-macro.html',
      controller: 'FinishMacroController'
    })

    // macro 설정 완료 화면
    .state('menu.advanced.add-macros.macro-done', {
      auth: true,
      url: '/macro-complete',
      templateUrl: 'views/add-macros/macro-done.html',
      controller: 'MacroDoneController'
    })

    // macro schedule 설정 화면
    .state('menu.advanced.add-macros.macro-schedule', {
      auth: true,
      url: '/macro-schedule',
      templateUrl: 'views/add-macros/macro-schedule.html',
      controller: 'MacroScheduleController'
    })

    .state('menu.advanced.add-macros.macro-commands', {
      auth: true,
      url: '/commands',
      templateUrl: 'views/add-macros/macro-commands.html',
      controller: 'MacroCommandsController'
    })

    // 설정 완료 후 이동할 화면 선택 화면
    .state('menu.advanced.add-macros.next-action', {
      auth: true,
      url: '/next',
      template: '<next-action continue-state="menu.advanced.add-macros.macro-type" back-state="menu.advanced.add-macros.choose-room"></next-action>'
    })

    // ********************************************************
    // Advanced Menu - Edit macros
    // ********************************************************

    .state('menu.advanced.edit-macros', {
      auth: true,
      abstract: true,
      url: '/edit-macros',
      template: '<div ui-view></div>',
      controller: function($scope) {
        $scope.addMacro = {'room': {}, 'steps': [], 'button': {}, 'disablePopup': false, 'linkId': null,
          'doneScreen': {'index': 0, 'devices': []}, 'currentDevice': {}};
        $scope.editMacro = {'mainDevice': {}, 'totalItems': 60, 'currentPage': 1 };
        $scope.client = {'page': {}};
        $scope.macroType = {id : null};
      }
    })

    // room 선택 화면
    .state('menu.advanced.edit-macros.choose-room', {
      auth: true,
      url: '/choose-room',
      templateUrl: 'views/add-macros/choose-room.html',
      controller: 'EditMacroRoomController'
    })

    // macro 를 수정할 button, device 선택 화면
    .state('menu.advanced.edit-macros.macro-simulator', {
      auth: true,
      url: '/:roomId/simulator',
      templateUrl: 'views/edit-macros/macro-simulator.html',
      controller: 'MacroSimulatorController'
      // ,
      // resolve: {
      //   devices: function($q, $stateParams, toastr, Systems) {
      //     var d = $q.defer();

      //     Systems.updateRoomDevices($stateParams.roomId)
      //     .then(function(data) {
      //       console.log(data);
      //       var roomDevices = Systems.getRoomDevices();
      //       d.resolve(roomDevices.devices);
      //     })
      //     .catch(function (error) {
      //       toastr.error(error);
      //       d.reject(error);
      //     });

      //     return d.promise;
      //   }
      // }

    })

    // macro device, commands 입력
    .state('menu.advanced.edit-macros.finish', {
      auth: true,
      url: '/finish',
      templateUrl: 'views/add-macros/edit-macro.html',
      controller: 'EditMacroController'

    })

    // macro 설정 완료 화면
    .state('menu.advanced.edit-macros.macro-done', {
      auth: true,
      url: '/macro-complete',
      templateUrl: 'views/add-macros/macro-done.html',
      controller: 'EditMacroDoneController'
    })

    .state('menu.advanced.edit-macros.macro-commands', {
      auth: true,
      url: '/commands',
      templateUrl: 'views/add-macros/macro-commands.html',
      controller: 'EditMacroCommandsController'
    })

    // 설정 완료 후 이동할 화면 선택 화면
    .state('menu.advanced.edit-macros.next-action', {
      auth: true,
      url: '/next',
      template: '<next-action continue-state="menu.advanced.edit-macros.macro-simulator" back-state="menu.advanced.edit-macros.choose-room"></next-action>',
      controller: function ($scope) {

      }
    })



    // ********************************************************
    // Advanced Menu - Add a room
    // ********************************************************

    .state('menu.advanced.add-room', {
      auth: true,
      abstract: true,
      url: '/add-room',
      template: '<div ui-view></div>',
      controller: function($scope) {

      },
      resolve: {
        // base station 검색 결과 목록
        searchResults: function ($q, Systems) {
          var d = $q.defer();
          // deviceName 에 hcm-c1 이 포함되어 있는 경우 base station 찾기
          Systems.searchHardware(true, 'hcm-c1').then(
            function(data) {
              console.log(data);
              d.resolve(data);
            },
            function (error) {
              alert(error);
              d.reject(error);
            }
          );
          return d.promise;
        }
      }
    })

    // base station 목록 표시 후 base station 선택과 함께 room 생성 화면
    .state('menu.advanced.add-room.select', {
      auth: true,
      url: '/select',
      templateUrl: 'views/add-rooms/select-room.html',
      controller: 'SelectRoomController'
    })
    // .state('menu.advanced.add-room.link-remote', {
    //   url: '/link-remote',
    //   templateUrl: 'views/add-rooms/link-remote.html',
    //   controller: 'LinkRemoteController'
    // })


    // ********************************************************
    // Advanced Menu - Add a remote
    // ********************************************************

    .state('menu.advanced.add-remote', {
      auth: true,
      abstract: true,
      url: '/add-remote',
      template: '<div ui-view></div>',
      controller: function($scope) {
        $scope.addRemote = {'selection': null, 'room': null};
      },
      resolve: {
        // remote 검색 결과 목록
        searchResults: function ($q, Systems) {
          var d = $q.defer();
          // deviceName 에 hcm-r1 이 포함되어 있는 경우 remote 찾기
          Systems.searchHardware(true, 'hcm-r1').then(
            function(data) {
              console.log(data);
              d.resolve(data);
            },
            function (error) {
              alert(error);
              d.reject(error);
            }
          );
          return d.promise;
        }
      }
    })

    // remote 목록을 표시하고 선택 후 remote 를 room 에 set 하는 화면
    .state('menu.advanced.add-remote.select', {
      auth: true,
      url: '/select',
      templateUrl: 'views/add-remotes/select-remote.html',
      controller: 'SelectRemoteController'
    })

    .state('menu.advanced.add-remote.available-rooms', {
      auth: true,
      url: '/rooms',
      templateUrl: 'views/add-remotes/available-rooms.html',
      controller: 'AvailableRoomsController'
    })


    // ********************************************************
    // Advanced Menu - Edit device UI
    // ********************************************************

    .state('menu.advanced.device', {
      auth: true,
      abstract: true,
      url: '/device',
      template: '<div ui-view></div>',
      controller: function($scope, Systems) {
        $scope.deviceMenu = {'roomId': null, 'deviceId': null};
        $scope.system = Systems.getCurrentSystem();
      }
    })

    // room, device 선택 화면
    .state('menu.advanced.device.select', {
      auth: true,
      url: '/select',
      templateUrl: 'views/device-menu/choose-device.html',
      controller: 'DeviceSelectionController'
    })

    // device button layout 편집 화면
    .state('menu.advanced.device.edit-layout', {
      auth: true,
      url: '/edit',
      templateUrl: 'views/device-menu/edit-layout.html',
      controller: 'DeviceMenuLayoutController'
    })

    // ********************************************************
    // Advanced Menu - Edit main menu UI
    // ********************************************************

    .state('menu.advanced.main', {
      auth: true,
      abstract: true,
      url: '/main',
      template: '<div ui-view></div>',
      controller: function($scope) {
        $scope.mainMenu = { 'room': {}, 'mainDevice': {}};
      }
    })

    // room 선택 화면
    .state('menu.advanced.main.choose-room', {
      auth: true,
      url: '/choose-room',
      templateUrl: 'views/main-menu/choose-room.html',
      controller: function($scope, $state, Systems) {
        $scope.doNext = function( ) {
          // main device 얻어와서 저장
          Systems.updateMainDevice($scope.mainMenu.room.id).then(function(response) {
            $state.go('menu.advanced.main.edit-layout');
          }, function(error) {
            alert(error);
          });
        };
      }
    })

    // entertainment main screen layout 편집 화면
    .state('menu.advanced.main.edit-layout', {
      auth: true,
      url: '/edit',
      templateUrl: 'views/main-menu/edit-layout.html',
      controller: 'MainMenuLayoutController'
    })

    // ********************************************************
    // Advanced Menu - Learn an ir device
    // ********************************************************

    .state('menu.advanced.learn-ir', {
      auth: true,
      abstract: true,
      url: '/learn-ir',
      template: '<div ui-view></div>',
      controller: function($scope, Systems) {
        $scope.system = Systems.getCurrentSystem();
        $scope.learnIr = { exists: null, roomId: null, deviceId: null, selectedBtn: null};
      }
    })

    // existing device, new device 선택 화면
    .state('menu.advanced.learn-ir.options', {
      auth: true,
      url: '',
      templateUrl: 'views/learn-ir/new-or-existing.html',
      controller: 'NewOrExistingController'
    })

    // room, device 선택 화면
    .state('menu.advanced.learn-ir.select-device', {
      auth: true,
      url: '/existing',
      templateUrl: 'views/learn-ir/existing-device.html',
      controller: 'ExistingDeviceController'
    })

    // 새 device 정보 입력 화면
    .state('menu.advanced.learn-ir.new-device', {
      auth: true,
      url: '/new',
      templateUrl: 'views/learn-ir/new-device.html',
      controller: 'NewDeviceController',
      resolve: {
        // device category 얻기
        categories: function(Database) {
          return Database.retreiveDeviceTypes();
        }
      }
    })

    // button learn 화면
    .state('menu.advanced.learn-ir.edit', {
      auth: true,
      url: '/edit',
      templateUrl: 'views/learn-ir/edit-ir.html',
      controller: 'EditIrController'
    })

    // ********************************************************
    // System Overview
    // ********************************************************

    .state('menu.system-overview', {
      auth: true,
      url: '/system-overview',
      templateUrl: 'views/system-overview.html',
      controller: 'SystemOverviewController'
    })

    // ********************************************************
    // Account Settings - Change account settings for user
    // ********************************************************

    .state('account-settings', {
      auth: true,
      abstract: true,
      url: '/account-settings',
      template: '<div class="editor-container" ui-view></div>',
      controller: function ($scope, user) {
        $scope.user = user;
      },
      resolve: {
        // 현재 사용자 정보 얻기
        user: function(Auth) {
          return Auth.currentUser();
        }
      }
    })

    // 사용자 정보 설정 화면: change email, change password 메뉴 링크
    .state('account-settings.main', {
      auth: true,
      url: '',
      templateUrl: 'views/account/settings.html',
      controller: function ($scope, user) { }
    })

    // email 변경 화면
    .state('account-settings.change-email', {
      auth: true,
      url: '/change-email',
      templateUrl: 'views/account/change-email.html',
      controller: 'ChangeEmailController'
    })

    // password 변경 화면
    .state('account-settings.change-password', {
      auth: true,
      url: '/change-password',
      templateUrl: 'views/account/change-password.html',
      controller: 'ChangePasswordController'
    })


    // ********************************************************
    // System Settings - Change system settings
    // ********************************************************

    .state('system-settings', {
      auth: true,
      abstract: true,
      url: '/system-settings',
      template: '<div class="editor-container" ui-view></div>',
      controller: function ($scope) {

      }
    })

    // system 설정 메인 화면
    .state('system-settings.main', {
      auth: true,
      url: '',
      templateUrl: 'views/system-settings.html',
      controller: 'SystemSettingsController',
      resolve: {
        // system 정보 얻기
        currentSystem: function($q, $window, Systems) {
          var d = $q.defer();
          if (Systems.getCurrentSystem()) {
            console.log('in resolve');
            d.resolve(Systems.getCurrentSystem());
          } else {
            var user = JSON.parse($window.localStorage.getItem('hcm_editor'));
            Systems.updateSystem(user.system_id).then(function(data) {
              d.resolve(Systems.getCurrentSystem());
            }).catch(function(error) {
              d.reject(error);
            });
          }
          return d.promise;
        },

        // timezone 목록 얻기
        timeZones: function($q, Timezones) {
          var d = $q.defer();

          Timezones.getAll().then(function(data) {
            d.resolve(data);
          }).catch(function(error) {
            d.reject(error);
          });

          return d.promise;
        }
      }
    })

    // system 목록 표시, system 삭제 화면
    .state('system-settings.delete', {
      auth: true,
      url: '/delete',
      templateUrl: 'views/system-delete.html',
      controller: 'SystemDeleteController',
      resolve: {
        // 사용자의 system 목록 얻기
        resolvedSystems: function(Systems) {
          return Systems.fetch();
        }
      }
    })

    // base station 변경 화면
    .state('system-settings.replace', {
      auth: true,
      url: '/replace',
      template: '<div ui-view></ui-view>',
      controller: function ($scope, Systems) {
        $scope.system = Systems.getCurrentSystem();
        $scope.bsReplace = {};
      }
    })

    // 변경할 base station 선택 화면
    .state('system-settings.replace.main', {
      auth: true,
      url: '/main',
      templateUrl: 'views/bs-replace/select-bs.html',
      controller: 'ReplaceMainController'
    })

    .state('system-settings.replace.master', {
      auth: true,
      url: '/master',
      templateUrl: 'views/bs-replace/auth-base.html',
      controller: 'ReplaceMasterController',
      resolve: {
        availableModels: function($q, Registration) {
          var d = $q.defer();

          Registration.getModelTypes().then(
            function(response) {
              if(response.data.result) {
                console.log('Loaded from resolve!');
                console.log(response.data.data);
                d.resolve(JSON.parse(response.data.data));
              } else {
                d.reject();
              }
            },
            function(error) {
              alert('Please try again');
            }
          );
          return d.promise;
        }
      }
    })
    .state('system-settings.replace.slave', {
      auth: true,
      url: '/slave',
      templateUrl: 'views/bs-replace/replace-slave.html',
      controller: 'ReplaceSlaveController',
      resolve: {
        // base station 검색 결과 목록
        searchResults: function ($q, Systems) {
          var d = $q.defer();
          // deviceName 에 hcm-c1 이 포함되어 있는 경우 base station 찾기
          Systems.searchHardware(true, 'hcm-c1').then(
            function(data) {
              console.log(data);
              d.resolve(data);
            },
            function (error) {
              alert(error);
              d.reject(error);
            }
          );
          return d.promise;
        }
      }
    })

    .state('system-settings.replace.target', {
      auth: true,
      url: '/target',
      templateUrl: 'views/bs-replace/replace-target.html',
      controller: 'ReplaceTargetController'
    })

    .state('system-settings.replace.prompt', {
      auth: true,
      url: '/prompt',
      templateUrl: 'views/bs-replace/prompt.html',
      controller: 'ReplacePromptController'
    })

    // ********************************************************
    // Download
    // ********************************************************


    .state('menu.download', {
      auth: true,
      url: '/download',
      templateUrl: 'views/download.html',
      controller: function($scope, currentUser) {
        $scope.currentUser = currentUser;
      }
    });
});
