/* Amber package loading
  usage example:
  amber.load({
    files: ['MyCategory1.js', 'MyCategory2.js'],
    ready: function() {smalltalk.Browser._open()}
  })
*/

amber = (function() {
  var that = {};

  var scripts = document.getElementsByTagName("script");
  var src     = scripts[ scripts.length - 1 ].src;
  var home    = src.split("/").slice(0, -2).join("/") + "/";
  var nocache = '?' + (new Date()).getTime();

  var debug;
  var deploy;

  var localStorageSource = [];
  var localPackages;
  var spec;

  that.toggleIDE = function() {
    if ($('#jtalk').length == 0) {
      smalltalk.Browser._open();
    } else if ($('#jtalk').is(':visible')) {
      smalltalk.TabManager._current()._close();
    } else {
      smalltalk.TabManager._current()._open();
    }
    return false;
  }

  that.load = function(obj) {
    spec = obj || {};

    // In deployment mode, only the compressed version of Kernel
    // and Canvas are loaded
    deploy = spec.deploy || false;
    debug = spec.debug || false;

    // When debug is turned on, logs are written to the console,
    // and the user will be prompted before they leave the page.
    if (debug) {
      window.onbeforeunload = function(){ return 'You will loose all code that you have not committed'; }
    }

    // Allow loading default Amber files from a different location
    // e.g. http://amber-lang.net/amber/
    if (spec.home) home = spec.home;

    // Specify a version string to avoid wrong browser caching
    if (spec.version) {
      nocache = '?' + spec.version;
    }

    loadDependencies();
    loadJS('compat.js');
    loadJS('boot.js');

    populateLocalPackages();

    if (deploy) {
      loadPackages([
        'Kernel-Objects.deploy',
        'Kernel-Classes.deploy',
        'Kernel-Methods.deploy',
        'Kernel-Collections.deploy',
        'Kernel-Exceptions.deploy',
        'Kernel-Transcript.deploy',
        'Canvas.deploy'
      ]);
    } else {
      loadIDEDependencies();
      loadCSS('amber.css');

      loadPackages([
        'Kernel-Objects',
        'Kernel-Classes',
        'Kernel-Methods',
        'Kernel-Collections',
        'Kernel-Exceptions',
        'Kernel-Transcript',
        'Canvas',
        'Compiler',
        'parser',
        'IDE',
        'SUnit',
        'Examples',
        'Benchfib',
        'Kernel-Tests'
      ]);
    }

    var additionalFiles = spec.packages || spec.files;
    if (additionalFiles) {
      loadPackages(additionalFiles, spec.prefix);
    }

    // Always load all local packages
    for (name in localPackages) {
      log('Local package:  ' + name);
      var sourceCode = unescape(localPackages[name]);
      sourceCode += "\nsmalltalk.Package._init_('"+name+"')";
      localStorageSource.push(sourceCode);
    }

    // Be sure to setup & initialize smalltalk classes
    loadJS('init.js');
    initializeSmalltalk();
  };

  function loadPackages(names, prefix){
    var name, url;
    var prefix = prefix || 'js';

    for (var i=0; i < names.length; i++) {
      name = names[i].split(/\.js$/)[0];

      // Only load package from the server if it isn't stored in
      // localStorage
      if (!(name in localPackages)) {
        log('Server package: ' + name);
        loadJS(name + '.js', prefix);
      }
    }
  };

  function loadJS(name, prefix) {
    var prefix = prefix || 'js';
    var name = name;

    if (!deploy) {
      name = name + nocache;
    }

    var url = home + prefix + '/' + name;
    var scriptString = '<script src="' + url + '" type="text/javascript"></script>';
    document.write(scriptString);
  };

  function loadCSS(name, prefix) {
    var prefix = prefix || 'css';
    var name = name;
    if (!deploy) {
      name = name + nocache;
    }

    var url = home + prefix + '/' + name;

    var link = document.createElement("link");
    link.setAttribute("rel", "stylesheet");
    link.setAttribute("type", "text/css");
    link.setAttribute("href", url);
    document.getElementsByTagName("head")[0].appendChild(link);
  };

  function loadDependencies() {
    if (typeof jQuery == 'undefined') {
      loadJS('lib/jQuery/jquery-1.6.4.min.js');
    }

    if ((typeof jQuery == 'undefined') || (typeof jQuery.ui == 'undefined')) {
      loadJS('lib/jQuery/jquery-ui-1.8.16.custom.min.js');
    }
  };

  function loadIDEDependencies() {
    loadJS('lib/jQuery/jquery.textarea.js');
    loadJS('lib/CodeMirror/codemirror.js');
    loadJS('lib/CodeMirror/smalltalk.js');
    loadCSS('lib/CodeMirror/codemirror.css', 'js');
    loadCSS('lib/CodeMirror/amber.css', 'js');
  };

  // This will be called after JS files have been loaded
  function initializeSmalltalk() {

    window.smalltalkReady = function() {

      for (var i=0; i < localStorageSource.length; i++) {
        eval(localStorageSource[i]);
      }

      if (deploy) {
        smalltalk.setDeploymentMode();
      }

      if (spec.ready) {
        spec.ready();
      }
    }
  };

  function populateLocalPackages(){
    var localStorageRE = /^smalltalk\.packages\.(.*)$/;
    localPackages = {};

    var match, key;

    for(var i=0; i < localStorage.length; i++) {
      key = localStorage.key(i);

      if (match = key.match(localStorageRE)) {
        localPackages[match[1]] = localStorage[key];
      }
    }

    return localPackages;
  };

  function clearLocalPackages() {
    for (var name in localPackages) {
      log('Removing ' + name + ' from local storage');
      localStorage.removeItem('smalltalk.packages.' + name);
    }
  };

  function log(string) {
    if (debug) {
      console.log(string);
    }
  }

  return that;
})();

window.loadAmber = amber.load;
window.toggleAmberIDE = amber.toggleIDE;