(function () {
  "use strict";

  var IS_LOCAL  = /(:\/\/localhost|file:\/\/)/.test(document.location.href);

  require.config({
      waitSeconds :   (IS_LOCAL? 10 : 45)
    , paths: {

      // core
        app:            '../modules/core/app/app'
      , config:         '../modules/core/config/config'
      , polyfill:       '../modules/core/polyfill/polyfill'
      , overrides:      '../modules/core/overrides/overrides'
      , utilities:      '../modules/core/utilities/utilities'
      , extensions:     '../modules/core/extensions/extensions'
      , storage:        '../modules/core/storage/storage'

      // requireJs
      , almond:         '../js/libs/require/almond'
      , text:           '../js/libs/require/text'
      , css:            '../js/plugins/require-css/require-css'
      , normalize:      '../js/plugins/require-css/normalize'
      , json:           '../js/plugins/requirejs-plugins/json'
      , async:          '../js/plugins/requirejs-plugins/async'

      // support
      , modernizr:      '../js/plugins/modernizr'
      , selectivzr:     '../js/plugins/selectivzr'

      // plugins/libs
      , jquery:         '../js/libs/jquery/jquery'
      , jqm:            '../js/libs/jquery-mobile/jquery-mobile'
      , i18next:        '../js/plugins/i18next/i18next'
      , renderjs:       '../js/plugins/renderjs/renderjs'
      , jio:            '../js/libs/jio/jio'
      , md5:            '../js/libs/jio/md5'
      , localstorage:   '../js/libs/jio/localstorage'
      , indexstorage:   '../js/libs/jio/indexstorage'
      , complex_queries:'../js/libs/jio/complex_queries'
      , validval:       '../js/plugins/validval/validval'

      // page gadgets
      , address:          '../modules/ui/address/address'
      , basket:           '../modules/ui/basket/basket'
      , browser:          '../modules/ui/browser/browser'
      , confirm:          '../modules/ui/confirm/confirm'
      , description:      '../modules/ui/description/description'
      , details:          '../modules/ui/details/details'
      , footer:           '../modules/ui/footer/footer'
      , gallery:          '../modules/ui/gallery/gallery'
      , header:           '../modules/ui/header/header'
      , index:            '../modules/ui/index/index'
      , item:             '../modules/ui/item/item'
      , items:            '../modules/ui/items/items'
      , login:            '../modules/ui/login/login'
      , media:            '../modules/ui/media/media'
      , payment:          '../modules/ui/payment/payment'
      , refine:           '../modules/ui/refine/refine'
      , register:         '../modules/ui/register/register'
      , products:         '../modules/ui/products/products'
      , searchbar:        '../modules/ui/searchbar/searchbar'
      , seo:              '../modules/ui/seo/seo'
      , shipment:         '../modules/ui/shipment/shipment'
      , sorting:          '../modules/ui/sorting/sorting'
      , summary:          '../modules/ui/summary/summary'
      , teaser:           '../modules/ui/teaser/teaser'
      , terms:            '../modules/ui/terms/terms'
      , translate:        '../modules/ui/translate/translate'
      , pageheader:       '../modules/ui/pageheader/pageheader'
      , pagefooter:       '../modules/ui/pagefooter/pagefooter'
    }
    , shim: {
        'jqm':              { deps: ['jquery'], exports: 'mobile' }
      , 'jio':              { deps: ['md5'] }
      , 'localstorage':     { deps: ['jio', 'complex_queries'] }
      , 'indexstorage':     { deps: ['jio'] }
      , 'renderjs':         { deps: ['jquery'], exports: 'RenderJs' }
      , 'app':              { deps: ['jio'], exports: 'App' }
      , 'validval':         { deps: ['jquery'] }
    }
    , map: {
      '*': {
        'css': '../js/plugins/require-css/css'
      }
    }
  });


  require(['app', 'config'], function(App, Config) {

    var setup = new $.Deferred();
    var spec = {};
    var i;
    var def;

    spec.app = App;
    spec.config = Config;
    spec.setup = setup;

    // fallback for fast browsers...
    spec.fallbackLoader = {
      deferreds: [],
      args: [],
    };

    // expose App once everything is loaded
    spec.setup.done(function(App, Config) {

      // expose configuration - settings
      App.settings = Config.settings;
      // expose configuration - storages
      App.storage = Config.storage;

      for (i = 0; i < window.fallbackLoader.deferreds.length; i += 1) {
        window.fallbackLoader.deferreds[i]
          .resolve(window.fallbackLoader.args[i]);
      }

      // cleanup
      delete window.fallbackLoader;
    });

    spec.configuration_setter = function (spec) {
      spec.config.set(spec);
    };

    // expose fallback
    window.fallbackLoader = spec.fallbackLoader;

    // initialize
    App.initialize(spec);
  });
}());