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

/*global app:true*/

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

app.run( function ($rootScope, $state, $stateParams, $interval, toastr, Auth, Systems) {

  // version 불러오기
  Systems.getSystemVersion().then(function(response) {
    $rootScope.version = response;
  }).catch(function(error) {
    toastr.error(error);
  });

  $rootScope.env = {};

  // 환경설정 불러오기
  Systems.getSystemEnv().then(function(response) {
    $rootScope.env = response;

    // 홈페이지 타이틀 변경
    angular.element('head title').html(response.pageTitle);
  }).catch(function(error) {
    toastr.error(error);
  });

  $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.');
      }
    });
  });

  // 페이지를 계속 열어놓은 경우 자동으로 로그아웃 되는 기능을 만들기 위해 매초마다 token 이 유효하지 않은 경우 자동으로 로그인 페이지로 이동시킴
  // token 은 로그인 후 24시간 동안 유효하므로, 현재 시간과 로그인한 timestamp 를 비교하여 24시간이 지났으면 로그아웃 된 것으로 판단함
  // 페이지 URL 에 menu 가 포함되어 있는 경우가 로그인 후 사용 가능한 메뉴들로 생각해서, 현재 URL 에 menu 가 포함되어 있는 경우에만 이 동작을 실행함
  $interval(function() {
    if ($state.current.name.match('menu')) {
      Auth.currentUser().then(function(user) {
        if (user && user.timestamp) {
          var now = parseInt(+new Date() / 1000, 10);

          if (now > user.timestamp + 60 * 60 * 24) {
            Auth.removeCurrentUser();
            $state.go('login');
          }
        }
      });
    }
  }, 1000);

});

/**
 * @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');
});

// 로컬 개발을 위해 http 요청 중 URL 에 /api/ 가 포함되어 있는 경우(=> 프로토콜 요청인 경우) alpha 서버 주소를 붙여서 요청함.
// 커밋할 때와 alpha 서버에 업로드할 때 반드시 삭제해야함
/*
 app.config(function($httpProvider) {
 $httpProvider.interceptors.push(function($q) {
 return {
 request: function(config) {
 if (config.url.match('/api/')) {
 //config.url = 'https://alpha.urcsmarthome.com' + config.url;
 config.url = 'https://eng.urchomeset.com' + config.url;
 }

 return config || $q.when(config);
 }
 };
 });
 });
 */

// 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: '/',
      controller: function($state, Auth) {
        // 로그인 되어 있으면 account-settings 페이지로 이동
        // 로그인 되어 있지 않으면 login 페이지로 이동
        Auth.currentUser().then(function(user) {
          if(user) {
            $state.go('account-settings.main');
          } else {
            $state.go('login');
          }
        });
      }
    })

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

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

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

    // normal editor 에서 system-select 를 했는데 해당 system 이 dealer 에게 assign 되어 있어서 넘어온 경우
    .state('auto-login', {
      auth: false,
      url: '/auto-login/:systemId/:dealerId',
      controller: function ($state, $stateParams, toastr, User) {
        if (sessionStorage.getItem('credentials')) {
          var data = angular.copy(JSON.parse(sessionStorage.getItem('credentials')));
          sessionStorage.removeItem('credentials');

          data.simple = 1;

          var jsonData = JSON.stringify(data);  // 아이디/패스워드/simple
          console.log(jsonData);

          // 로그인
          User.login(jsonData)
            .then( function(data) {
              if(data.result) {
                if (data.status) {  // result=true, status=true 일 때 로그인 처리
                  var systemInfo = {
                    systemId: $stateParams.systemId,
                    dealerId: $stateParams.dealerId
                  };
                  sessionStorage.setItem('systemInfo', JSON.stringify(systemInfo));

                  // 로그인 성공하면 account-settings.main 으로 이동
                  $state.go('account-settings.main');
                }
              } else {
                toastr.error(data.error);
              }
            })
            .catch(toastr.error);
        }
      }
    })

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

        var systemInfo = JSON.parse(sessionStorage.getItem('systemInfo'));
        if (systemInfo && systemInfo.dealerId) {
          $scope.dealerId = systemInfo.dealerId;
        }

        $scope.getDealer = function () {
          Systems.getDealer(systemInfo.systemId).then(function (data) {
            if (data.result) {
              $scope.dealerInfo = data;

              var modal = $modal({
                scope: $scope,
                title: '',
                placement: 'top',
                template: 'views/user-login-change/modal-tpls/dealer-info.html',
                show: false
              });

              modal.$promise.then(modal.show);
            }
          })
            .catch(toastr.error);
        };
      },
      resolve: {
        // 현재 사용자 정보 얻기
        user: function(Auth) {
          return Auth.currentUser();
        }
      }
    })

    // 사용자 정보 설정 화면: change email, change password 메뉴 링크
    .state('account-settings.main', {
      auth: true,
      url: '',
      templateUrl: 'views/user-login-change/account/settings.html',
      controller: function ($scope, $state, User) {
        $scope.logoutUser = function () {
          User.logout();
          sessionStorage.removeItem('systemInfo');
          window.location = '../';
        };
      }
    })

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

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

    // programming access 변경 화면
    .state('account-settings.restrict-programming-access', {
      auth: true,
      url: '/restrict-programming-access',
      templateUrl: 'views/user-login-change/account/restrict-programming-access.html',
      controller: 'RestrictProgrammingAccessController',
      resolve: {
        // 현재 사용자 allow_edit 값 얻기
        option: function ($q, User) {
          var d = $q.defer();

          User.getInstallerOption().then(function (response) {
            d.resolve(response.option);
          }, function (error) {
            d.reject(error);
          });

          return d.promise;
        }
      }
    });
});
