'use strict';

window.addEventListener('error', function (err) {
  console.error("Uncaught Exception:");
  console.log(err);
});

// TODO where to place this?
var urlPrefix = './'; // or '/'

angular.module('yololiumApp', [
  'ui.bootstrap'
, 'ui.router'
, 'oauth3'
, 'daplie'
, 'steve'
/*
  'ngSanitize'
*/
]).config([
    '$urlRouterProvider'
  , '$stateProvider'
  , '$httpProvider'
  , 'stConfig'
  , function ($urlRouterProvider, $stateProvider, $httpProvider, StApi) {
    var rootTemplate = $('.ui-view-body').html();

    // https://daplie.com/connect/#/authorization_dialog/state=9124678613152355&response_type=token&scope=*&client_id=ID__1a503bda47a3fe3a00543166333f&redirect_uri=https://oauth3.org/oauth3.html%3Fprovider_uri=https%253A%252F%252Foauth3.org&origin=&referer=https://oauth3.org/&host=oauth3.org
    //$urlRouterProvider.otherwise('/');
    $stateProvider
      .state('root', {
        url: '/'
      , views: {
          body: {
            template: rootTemplate
          , controller: [
              '$scope'
            , 'DaplieApiSession'
            , 'DaplieApiRequest'
            , function ($scope, DaplieApiSession, DaplieApiRequest) {
              var MC = this;

              MC.urlsafe = function (name) {
                return name.toLowerCase().replace(/[^\-\w]/, '').replace(/s$/, '');
              };

              function prefetch(session) {
                console.log('DEBUG prefetch');
                // Prefetching
                return DaplieApiRequest.profile(session).then(function (profile) {
                  console.log('DEBUG profile');
                  console.log(profile);
                  //DaplieApiRequest.stake(session, profile.homeStakeAppScopedId);
                  //DaplieApiRequest.ward(session, profile.homeStakeAppScopedId, profile.homeWardAppScopedId);
                });
              }

              DaplieApiSession.checkSession(prefetch);
              DaplieApiSession.onLogin($scope, prefetch);
            }]
          , controllerAs: 'MC'
          }
        }
      })

      .state('logout', {
        url: '/logout/:browserState'
      , views: {
          body: {
            template: ''
            // DestroySessionController
          , controller: [
              '$window'
            , '$stateParams'
            , 'DaplieApiSession'
            , function ($window, $stateParams, DaplieApiSession) {
              DaplieApiSession.destroy().then(function () {
                var state = $stateParams.browserState;
                $window.location.href = '/oauth3.html#logout_callback=true&state=' + state;
              });
            }]
          , controllerAs: 'DSC'
          }
        }

      })

      /*
      .state('authorization-dialog', {
        url: '/authorization_dialog/{query:.+}'
      , views: {
          body: {
            templateUrl: urlPrefix + 'views/authorization-dialog.html'
          , controller: 'AuthorizationDialogController as ADC'
          }
        }
      })
      */
      .state('authorization-dialog', {
        url: '/authorization_dialog/'
      , views: {
          body: {
            templateUrl: urlPrefix + 'views/authorization-dialog.html'
          , controller: 'AuthorizationDialogController as ADC'
          }
        }
      })

      .state('account', {
        url: '/account/'
      , views: {
          body: {
            templateUrl: urlPrefix + 'views/my-account.html'
          , controller: 'MyAccountController as MAC'
          }
        }
      })
      ;

    // send creds
    $httpProvider.defaults.withCredentials = true;
    // alternatively, register the interceptor via an anonymous factory?
    $httpProvider.interceptors.push([ '$q', function($q) {
      var recase = window.Recase.create({ exceptions: {} });

      function isApiUrl(url) {
        // TODO provide a list of known-good API urls in StApi and loop
        return !/^https?:\/\//.test(url)
          || url.match(StApi.apiPrefix)
          || url.match(StApi.oauthPrefix)
          ;
      }

      return {
        'request': function (config) {
          if (config.data
              && isApiUrl(config.url)
              && /json/.test(config.headers['Content-Type'])
          ) {
            config.data = recase.snakeCopy(config.data);
          }

          return config;
        }
      , 'requestError': function (rejection) {
          return rejection;
        }
      , 'response': function (response) {
          var config = response.config;
          var err;

          // our own API is snake_case (to match webApi / ruby convention)
          // but we convert to camelCase for javascript convention
          if (isApiUrl(config.url) && /json/.test(response.headers('Content-Type'))) {
            response.data = recase.camelCopy(response.data);
            if ('string' === typeof response.data.error) {
              err = new Error(response.data.errorDescription);
              err.code = response.data.error;
              err.uri = response.data.errorUri;
              return $q.reject(err);
            }
            if ('object' === typeof response.data.error) {
              err = new Error(response.data.error.message);
              err.code = response.data.error.code;
              err.uri = response.data.error.uri;
              /*
              Object.keys(response.data.error).forEach(function (key) {
                err[key] = response.data.error[key];
              });
              */
              return $q.reject(err);
            }
          }
          return response;
        }
      , 'responseError': function (rejection) {
          return rejection;
        }
      };
    }]);

}]).run([
    '$rootScope'
  , '$timeout'
  , '$q'
  , '$http'
  , '$modal'
  , 'DaplieApi'
  , 'DaplieApiSession'
  , function ($rootScope, $timeout, $q, $http, $modal, DaplieApi, DaplieApiSession) {

  return DaplieApi.init({
    //appId: 'TEST_ID_871a371debefb91c919ca848'
    //appId: 'ID__b5db805e27cc27a0ee8eddf42f46'
    appId: 'oauth3.org'
  , appVersion: '2.1.0'
  , clientUri: 'oauth3.org'
  , clientAgreeTos: 'oauth3.org/tos/draft'
  , invokeLogin: function (opts) {
      console.info('login invoked');
      return $modal.open({
        templateUrl: urlPrefix + 'views/login-v3.html'
      , controller: 'LoginController3 as LC'
      , backdrop: 'static'
      , keyboard: true
      , resolve: {
          myLoginOptions: [function () {
            return opts;
          }]
        }
      }).result;
    }
  }).then(function (DaplieApiConfig) {
    $rootScope.R = {};
    // attach after angular is initialized so that angular errors
    // don't annoy developers that forgot bower install
    window.addEventListener('error', function (err) {
      window.alert('Uncaught Exception: ' + (err.message || 'unknown error'));
    });

    // TODO get from config
    $http.get((DaplieApiConfig.apiBaseUri || DaplieApiConfig.providerUri)
      + '/api/org.oauth3.provider' + '/public/apps'
    ).then(function (resp) {
      $rootScope.R.ready = true;
      $rootScope.R.apps = resp.data.result.filter(function (app) {
        return app.live;
      });
    });

    // normally we'd do a background login here, but daplie.com/connect is already
    // is the provider, so no sense in doing that...
    return DaplieApiSession.checkSession().then(function () {
      $rootScope.rootReady = true;
      $rootScope.rootDeveloperMode = DaplieApiConfig.developerMode;
      $rootScope.R.dev = $rootScope.rootDeveloperMode;
    }, function () {
      $rootScope.rootReady = true;
      $rootScope.rootDeveloperMode = DaplieApiConfig.developerMode;
      $rootScope.R.dev = $rootScope.rootDeveloperMode;
    });
  });
}]);
