text: 'use strict';
  
  var unsupported, isaosp;
  
  if (window && window.navigator) {
    var rxaosp = window.navigator.userAgent.match(/Android.*AppleWebKit\/([\d.]+)/);
    isaosp = (rxaosp && rxaosp[1] < 537);
    if (!window.cordova && isaosp)
      unsupported = true;
    if (unsupported) {
      window.location = '#/unsupported';
    }
  }
  
  
  //Setting up route
  angular
    .module('copayApp')
    .config(function(historicLogProvider, $provide, $logProvider, $stateProvider, $urlRouterProvider, $compileProvider) {
      $urlRouterProvider.otherwise('/');
  
      $logProvider.debugEnabled(true);
      $provide.decorator('$log', ['$delegate',
        function($delegate) {
          var historicLog = historicLogProvider.$get();
  
          ['debug', 'info', 'warn', 'error', 'log'].forEach(function(level) {
            var orig = $delegate[level];
            $delegate[level] = function() {
  
              if (level == 'error')
                console.log(arguments);
  
              var args = [].slice.call(arguments);
              if (!Array.isArray(args)) args = [args];
              args = args.map(function(v) {
                try {
                  if (typeof v == 'undefined') v = 'undefined';
                  if (!v) v = 'null';
                  if (typeof v == 'object') {
                    if (v.message)
                      v = v.message;
                    else
                      v = JSON.stringify(v);
                  }
                  // Trim output in mobile
                  if ( window.cordova ) {
                    v = v.toString();
                    if (v.length > 1000) {
                      v = v.substr(0, 997) + '...';
                    }
                  }
                } catch (e) {
                  console.log('Error at log decorator:', e);
                  v = 'undefined';
                }
                return v;
              });
              try {
                if (window.cordova)
                  console.log(args.join(' '));
                historicLog.add(level, args.join(' '));
                orig.apply(null, args);
              } catch (e) {
                console.log('ERROR (at log decorator):', e, args[0]);
              }
            };
          });
          return $delegate;
        }
      ]);
  
      // whitelist 'chrome-extension:' for chromeApp to work with image URLs processed by Angular
      // link: http://stackoverflow.com/questions/15606751/angular-changes-urls-to-unsafe-in-extension-page?lq=1
      $compileProvider.imgSrcSanitizationWhitelist(/^\s*((https?|ftp|file|blob|chrome-extension):|data:image\/)/);
  
      $stateProvider
        .state('splash', {
          url: '/splash',
          needProfile: false,
          views: {
            'main': {
              templateUrl: 'views/splash.html',
              controller: function($scope, $timeout, $log, profileService, storageService, go) {
                storageService.getCopayDisclaimerFlag(function(err, val) {
                  if (!val) go.path('disclaimer');
  
                  if (profileService.profile) {
                    go.walletHome();
                  }
                });
  
                $scope.create = function(noWallet) {
                  $scope.creatingProfile = true;
  
                  $timeout(function() {
                    profileService.create({
                      noWallet: noWallet
                    }, function(err) {
                      if (err) {
                        $scope.creatingProfile = false;
                        $log.warn(err);
                        $scope.error = err;
                        $scope.$apply();
                        $timeout(function() {
                          $scope.create(noWallet);
                        }, 3000);
                      }
                    });
                  }, 100);
                };
              }
            }
          }
        });
  
        $stateProvider
        .state('translators', {
          url: '/translators',
          walletShouldBeComplete: true,
          needProfile: true,
          views: {
            'main': {
              templateUrl: 'views/translators.html'
            }
          }
        })
        .state('disclaimer', {
          url: '/disclaimer',
          needProfile: false,
          views: {
            'main': {
              templateUrl: 'views/disclaimer.html',
              controller: function($scope, $timeout, storageService, applicationService, go, gettextCatalog, isCordova) {
                storageService.getCopayDisclaimerFlag(function(err, val) {
                  $scope.agreed = val;
                  $timeout(function() {
                    $scope.$digest();
                  }, 1);
                });
  
                $scope.agree = function() {
                  if (isCordova) {
                    window.plugins.spinnerDialog.show(null, gettextCatalog.getString('Loading...'), true);
                  }
                  $scope.loading = true;
                  $timeout(function() {
                    storageService.setCopayDisclaimerFlag(function(err) {
                      $timeout(function() {
                        if (isCordova) {
                          window.plugins.spinnerDialog.hide();
                        }
                        applicationService.restart();
                      }, 1000);
                    });
                  }, 100);
                };
              }
            }
          }
        })
        .state('walletHome', {
          url: '/',
          walletShouldBeComplete: true,
          needProfile: true,
          views: {
            'main': {
              templateUrl: 'views/walletHome.html',
            },
          }
        })
        .state('unsupported', {
          url: '/unsupported',
          needProfile: false,
          views: {
            'main': {
              templateUrl: 'views/unsupported.html'
            }
          }
        })
        .state('payment', {
          url: '/uri-payment/:data',
          templateUrl: 'views/paymentUri.html',
          views: {
            'main': {
              templateUrl: 'views/paymentUri.html',
            },
          },
          needProfile: true
        })
        .state('selectWalletForPayment', {
          url: '/selectWalletForPayment',
          controller: 'walletForPaymentController',
          needProfile: true
        })
        .state('join', {
          url: '/join',
          needProfile: true,
          views: {
            'main': {
              templateUrl: 'views/join.html'
            },
          }
        })
        .state('import', {
          url: '/import',
          needProfile: true,
          views: {
            'main': {
              templateUrl: 'views/import.html'
            },
          }
        })
        .state('importProfile', {
          url: '/importProfile',
          templateUrl: 'views/importProfile.html',
          needProfile: false
        })
        .state('importLegacy', {
          url: '/importLegacy',
          needProfile: true,
          views: {
            'main': {
              templateUrl: 'views/importLegacy.html',
            },
          }
  
        })
        .state('create', {
          url: '/create',
          templateUrl: 'views/create.html',
          needProfile: true,
          views: {
            'main': {
              templateUrl: 'views/create.html'
            },
          }
        })
        .state('copayers', {
          url: '/copayers',
          needProfile: true,
          views: {
            'main': {
              templateUrl: 'views/copayers.html'
            },
          }
        })
        .state('preferences', {
          url: '/preferences',
          templateUrl: 'views/preferences.html',
          walletShouldBeComplete: true,
          needProfile: true,
          views: {
            'main': {
              templateUrl: 'views/preferences.html',
            },
          }
        })
        .state('preferencesLanguage', {
          url: '/preferencesLanguage',
          walletShouldBeComplete: true,
          needProfile: true,
          views: {
            'main': {
              templateUrl: 'views/preferencesLanguage.html'
            },
          }
        })
        .state('preferencesUnit', {
          url: '/preferencesUnit',
          templateUrl: 'views/preferencesUnit.html',
          walletShouldBeComplete: true,
          needProfile: true,
          views: {
            'main': {
              templateUrl: 'views/preferencesUnit.html'
            },
          }
        })
        .state('preferencesFee', {
          url: '/preferencesFee',
          templateUrl: 'views/preferencesFee.html',
          walletShouldBeComplete: true,
          needProfile: true,
          views: {
            'main': {
              templateUrl: 'views/preferencesFee.html'
            },
          }
        })
  
      .state('preferencesAdvanced', {
          url: '/preferencesAdvanced',
          templateUrl: 'views/preferencesAdvanced.html',
          walletShouldBeComplete: true,
          needProfile: true,
          views: {
            'main': {
              templateUrl: 'views/preferencesAdvanced.html'
            },
          }
        })
        .state('preferencesColor', {
          url: '/preferencesColor',
          templateUrl: 'views/preferencesColor.html',
          walletShouldBeComplete: true,
          needProfile: true,
          views: {
            'main': {
              templateUrl: 'views/preferencesColor.html'
            },
          }
        })
  
      .state('preferencesAltCurrency', {
          url: '/preferencesAltCurrency',
          templateUrl: 'views/preferencesAltCurrency.html',
          walletShouldBeComplete: true,
          needProfile: true,
          views: {
            'main': {
              templateUrl: 'views/preferencesAltCurrency.html'
            },
          }
        })
        .state('preferencesAlias', {
          url: '/preferencesAlias',
          templateUrl: 'views/preferencesAlias.html',
          walletShouldBeComplete: true,
          needProfile: true,
          views: {
            'main': {
              templateUrl: 'views/preferencesAlias.html'
            },
  
          }
        })
        .state('preferencesEmail', {
          url: '/preferencesEmail',
          templateUrl: 'views/preferencesEmail.html',
          walletShouldBeComplete: true,
          needProfile: true,
          views: {
            'main': {
              templateUrl: 'views/preferencesEmail.html'
            },
  
          }
        })
        .state('preferencesBwsUrl', {
          url: '/preferencesBwsUrl',
          templateUrl: 'views/preferencesBwsUrl.html',
          walletShouldBeComplete: true,
          needProfile: true,
          views: {
            'main': {
              templateUrl: 'views/preferencesBwsUrl.html'
            },
  
          }
        })
        .state('delete', {
          url: '/delete',
          templateUrl: 'views/preferencesDeleteWallet.html',
          walletShouldBeComplete: true,
          needProfile: true,
          views: {
            'main': {
              templateUrl: 'views/preferencesDeleteWallet.html'
            },
          }
        })
        .state('about', {
          url: '/about',
          templateUrl: 'views/preferencesAbout.html',
          walletShouldBeComplete: true,
          needProfile: true,
          views: {
            'main': {
              templateUrl: 'views/preferencesAbout.html'
            },
          }
        })
        .state('logs', {
          url: '/logs',
          templateUrl: 'views/preferencesLogs.html',
          walletShouldBeComplete: true,
          needProfile: true,
          views: {
            'main': {
              templateUrl: 'views/preferencesLogs.html'
            },
          }
        })
        .state('backup', {
          url: '/backup',
          templateUrl: 'views/backup.html',
          walletShouldBeComplete: true,
          needProfile: true,
          views: {
            'main': {
              templateUrl: 'views/backup.html'
            },
          }
        })
        .state('settings', {
          url: '/settings',
          controller: 'settingsController',
          templateUrl: 'views/settings.html',
          needProfile: false
        })
        .state('warning', {
          url: '/warning',
          controller: 'warningController',
          templateUrl: 'views/warning.html',
          needProfile: false
        })
  
      .state('add', {
          url: '/add',
          needProfile: true,
          views: {
            'main': {
              templateUrl: 'views/add.html'
            },
          }
        })
        .state('cordova', {
          url: '/cordova/:status',
          views: {
            'main': {
              controller: function($rootScope, $stateParams, $timeout, go) {
                switch ($stateParams.status) {
                  case 'resume':
                    $rootScope.$emit('Local/Resume');
                    break;
                };
                $timeout(function() {
                  $rootScope.$emit('Local/SetTab', 'walletHome', true);
                }, 100);
                go.walletHome();
              }
            }
          },
          needProfile: false
        });
    })
    .run(function($rootScope, $state, $log, gettextCatalog, uriHandler, isCordova, amMoment, profileService, $timeout, nodeWebkit) {
      FastClick.attach(document.body);
  
      // Auto-detect browser language
      var userLang, androidLang;
  
      if (navigator && navigator.userAgent && (androidLang = navigator.userAgent.match(/android.*\W(\w\w)-(\w\w)\W/i))) {
        userLang = androidLang[1];
      } else {
        // works for iOS and Android 4.x
        userLang = navigator.userLanguage || navigator.language;
      }
  
      userLang = userLang ? (userLang.split('-', 1)[0] || 'en') : 'en';
      gettextCatalog.setCurrentLanguage(userLang);
      amMoment.changeLocale(userLang);
  
      // Register URI handler, not for mobileApp
      if (!isCordova) {
        uriHandler.register();
      }
  
      if (nodeWebkit.isDefined()) {
        var gui = require('nw.gui');
        var win = gui.Window.get();
        var nativeMenuBar = new gui.Menu({
          type: "menubar"
        });
        try {
          nativeMenuBar.createMacBuiltin("Copay");
        } catch (e) {
          $log.debug('This is not OSX');
        }
        win.menu = nativeMenuBar;
      }
  
      var pageWeight = {
        walletHome: 0,
        copayers: -1,
        cordova: -1,
        payment: -1,
  
        preferences: 11,
        preferencesColor: 12,
        backup: 12,
        preferencesAdvanced: 12,
        delete: 13,
        preferencesLanguage: 12,
        preferencesUnit: 12,
        preferencesFee: 12,
        preferencesAltCurrency: 12,
        preferencesBwsUrl: 12,
        preferencesAlias: 12,
        preferencesEmail: 12,
        about: 12,
        logs: 13,
        translators: 13,
        disclaimer: 13,
        add: 11,
        create: 12,
        join: 12,
        import: 12,
        importLegacy: 13
      };
  
  
      var cachedTransitionState, cachedBackPanel;
  
      $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
  
  
        if (!profileService.profile && toState.needProfile) {
  
          // Give us time to open / create the profile
          event.preventDefault();
  
          // Try to open local profile
          profileService.loadAndBindProfile(function(err) {
            if (err) {
              if (err.message.match('NOPROFILE')) {
                $log.debug('No profile... redirecting');
                $state.transitionTo('splash');
              } else if (err.message.match('NONAGREEDDISCLAIMER')) {
                $log.debug('Display disclaimer... redirecting');
                $state.transitionTo('disclaimer');
              } else {
                throw new Error(err); // TODO
              }
            } else {
              $log.debug('Profile loaded ... Starting UX.');
              $state.transitionTo(toState.name || toState, toParams);
            }
          });
        }
  
        if (profileService.focusedClient && !profileService.focusedClient.isComplete() && toState.walletShouldBeComplete) {
  
          $state.transitionTo('copayers');
          event.preventDefault();
        }
  
        /*
         * --------------------
         */
  
        function cleanUpLater(e, e2) {
          var cleanedUp = false,
            timeoutID;
          var cleanUp = function() {
            if (cleanedUp) return;
            cleanedUp = true;
            e2.parentNode.removeChild(e2);
            e2.innerHTML = "";
            e.className = '';
            cachedBackPanel = null;
            cachedTransitionState = '';
            if (timeoutID) {
              timeoutID = null;
              window.clearTimeout(timeoutID);
            }
          };
          e.addEventListener("animationend", cleanUp, true);
          e2.addEventListener("animationend", cleanUp, true);
          e.addEventListener("webkitAnimationEnd", cleanUp, true);
          e2.addEventListener("webkitAnimationEnd", cleanUp, true);
          timeoutID = setTimeout(cleanUp, 500);
        };
  
        function animateTransition(fromState, toState, event) {
  
          if (isaosp)
            return true;
  
          // Animation in progress?
          var x = document.getElementById('mainSectionDup');
          if (x && !cachedTransitionState) {
            console.log('Anim in progress');
            return true;
          }
  
          var fromName = fromState.name;
          var toName = toState.name;
          if (!fromName || !toName)
            return true;
  
          var fromWeight = pageWeight[fromName];
          var toWeight = pageWeight[toName];
  
  
          var entering = null,
            leaving = null;
  
          // Horizontal Slide Animation?
          if (fromWeight && toWeight) {
            if (fromWeight > toWeight) {
              leaving = 'CslideOutRight';
            } else {
              entering = 'CslideInRight';
            }
  
            // Vertical Slide Animation?
          } else if (fromName && fromWeight >= 0 && toWeight >= 0) {
            if (toWeight) {
              entering = 'CslideInUp';
            } else {
              leaving = 'CslideOutDown';
            }
  
            // no Animation  ?
          } else {
            return true;
          }
  
          var e = document.getElementById('mainSection');
  
  
          var desiredTransitionState = (fromName || '-') + ':' + (toName || '-');
  
          if (desiredTransitionState == cachedTransitionState) {
            e.className = entering || '';
            cachedBackPanel.className = leaving || '';
            cleanUpLater(e, cachedBackPanel);
            //console.log('USing animation', cachedTransitionState);
            return true;
          } else {
            var sc;
            // Keep prefDiv scroll
            var contentDiv = e.getElementsByClassName('content');
            if (contentDiv && contentDiv[0])
              sc = contentDiv[0].scrollTop;
  
            cachedBackPanel = e.cloneNode(true);
            cachedBackPanel.id = 'mainSectionDup';
            var c = document.getElementById('sectionContainer');
            c.appendChild(cachedBackPanel);
  
            if (sc)
              cachedBackPanel.getElementsByClassName('content')[0].scrollTop = sc;
  
            cachedTransitionState = desiredTransitionState;
            return false;
          }
        }
  
        if (!animateTransition(fromState, toState)) {
          event.preventDefault();
          // Time for the backpane to render
          setTimeout(function() {
            $state.transitionTo(toState);
          }, 50);
        }
      });
    });
  