;(function(Path) {
  'use strict';



  var log = console.log;
  /*var log = function() {
    console.log.apply(console, ['Define'].concat([].slice.call(arguments)));
  };*/

  var head = document.getElementsByTagName('head')[0];
  var cssLoader = function(fileName) {
    var link = document.createElement('link');
    link.setAttribute('rel', 'stylesheet');
    link.setAttribute('type', 'text/css');
    link.setAttribute('href', fileName);
    head.appendChild(link);
    return true;
  };
  var jsLoader = function(fileName) {
    fileName = fileName.replace(/src\//,'');
    var script = document.createElement('script');
    script.setAttribute('type', script.type = 'text/javascript');
    script.onload = function(){

    };
    script.setAttribute('src', script.src = fileName);
    head.appendChild(script);
  };

  var InstantLoaders = [
    {name: '.scss', loader: cssLoader},
    {name: '.css', loader: cssLoader},
    {name: '.jsx', loader: jsLoader},
    {name: '.js', loader: jsLoader},
  ];

  var Ready = function() {}; Ready.prototype = {ready: true};
  var Wait = function(fileName) {this.fileName = fileName; this.wait = [];};
  Wait.prototype = {
    fileName: '',
    ready: false,
    resolving: 0,
    checkInstantLoad: function() {
      for( var i = 0, _i = InstantLoaders.length; i < _i; i++ ){
        const instantLoader = InstantLoaders[ i ];
        if(this.fileName.substr(-instantLoader.name.length).toLowerCase()===instantLoader.name){
          if(instantLoader.loader(this.fileName)) {
            return true;
          }
          break;
        }
      }
      return false;
    }
  };

  var wait = {
    exports: Ready()
  };
  var defined = {

  };
  var resolve = function(base, file) {
    return Path.resolve(Path.dirname(base), file);
  };
  var exec = function(def) {
    var exports = {};
    def.fn.apply(null, def.deps.map(function(dep) {
      if(dep === 'exports'){
        return exports;
      }

      return defined[resolve(def.fileName, dep)];
    }));
    defined[def.fileName] = exports;
    var waiters = wait[def.fileName].wait;
    if(wait[def.fileName] instanceof Wait){
      wait[ def.fileName ] = new Ready();
      for( var i = 0, _i = waiters.length; i < _i; i++ ){
        var waitElement = waiters[ i ];
        if( waitElement instanceof Wait ){
          waitElement.resolving--;
        }

      }
      for( var i = 0, _i = waiters.length; i < _i; i++ ){
        var waitElement = waiters[ i ];
        if( waitElement.resolving === 0 ){
          exec( waitElement.def )
        }

      }
    }
  };
  window.define = function(fileName, deps, fn) {
    fileName = Path.trim(fileName);
    defined[fileName] = {fileName:fileName, deps: deps, fn:fn};


    deps = deps.map(function(dep) {
      return dep === 'exports' ? 'exports': resolve(fileName, dep);
    });

    var unresolved = deps.filter(function(dep) {
      if(dep === 'exports'){
        return false;
      }
      var resolvedName = dep;
      var waiter = wait[resolvedName];

      if(!wait[resolvedName]){
        waiter = wait[resolvedName] = new Wait(resolvedName)
      }
      if(!waiter.ready){
        waiter.wait.push( fileName );
        if( waiter.checkInstantLoad() ){
          wait[ resolvedName ] = new Ready();
        }
      }
      return !wait[resolvedName].ready;
    });
    if(!(fileName in wait)){
      wait[fileName] = new Wait(fileName);
    }
    var waiter = wait[fileName];

    if(unresolved.length === 0){
      log(fileName, 'deps fullfilled');
      exec(defined[fileName])
    }else{
      log(fileName, 'is waiting for', unresolved);
      for( var i = 0, _i = unresolved.length; i < _i; i++ ){
        var unresolvedElement = unresolved[ i ];
        waiter.wait.push(resolve(fileName, unresolvedElement));
        waiter.resolving++;

      }
    }
  };
  window.define.wait = wait;
  window.define.defined = defined;
})(window.__Path);