// Generated by CoffeeScript 1.3.1
/*
#    klns.coffee
#    ~~~~~~~~~~~~~~~
#
#    Base Kaylee namespace declarations
#
#    :copyright: (c) 2012 by Zaur Nasibov.
#    :license: MIT, see LICENSE for more details.
*/

var Event, KayleeError, import_project, kl, on_project_imported, on_task_completed, on_worker_event, pj, post_message, util, __DEFINE_WORKER, _dom_include, _worker_include,
  __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  __slice = [].slice,
  __hasProp = {}.hasOwnProperty,
  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };

kl = {
  pj: {},
  config: {},
  AUTO_PROJECT_MODE: 0x2,
  MANUAL_PROJECT_MODE: 0x4,
  NO_SOLUTION: {
    '__klr__': 0x2
  },
  NOT_SOLVED: {
    '__klr__': 0x4
  }
};

pj = kl.pj;

try {
  window.kl = kl;
} catch (err) {

}

/*
#    klutil.coffee
#    ~~~~~~~~~~~~~
#
#    This is the base file of Kaylee client-side module.
#    It contains the util and shared code used by Kaylee.
#
#    :copyright: (c) 2012 by Zaur Nasibov.
#    :license: MIT, see LICENSE for more details.
*/


util = {};

kl.util = util;

util.is_function = function(obj) {
  return typeof obj === 'function';
};

util.ends_with = function(str, suffix) {
  return str.indexOf(suffix, str.length - suffix.length) !== -1;
};

Event = (function() {

  Event.name = 'Event';

  function Event(handler) {
    if (handler == null) {
      handler = null;
    }
    this.unbind = __bind(this.unbind, this);

    this.bind = __bind(this.bind, this);

    this.trigger = __bind(this.trigger, this);

    this.handlers = [];
    if (handler != null) {
      this.handlers.push(handler);
    }
    return;
  }

  Event.prototype.trigger = function() {
    var args, c, _i, _len, _ref;
    args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
    _ref = this.handlers;
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      c = _ref[_i];
      c.apply(null, args);
    }
  };

  Event.prototype.bind = function(handler) {
    this.handlers.push(handler);
  };

  Event.prototype.unbind = function(handler) {
    var t, _ref;
    if ((t = this.handlers.indexOf(handler)) > -1) {
      [].splice.apply(this.handlers, [t, t - t + 1].concat(_ref = [])), _ref;
    }
  };

  return Event;

})();

kl.Event = Event;

KayleeError = (function(_super) {

  __extends(KayleeError, _super);

  KayleeError.name = 'KayleeError';

  function KayleeError() {
    KayleeError.__super__.constructor.apply(this, arguments);
  }

  return KayleeError;

})(Error);

kl.KayleeError = KayleeError;

/*
#    klajax.coffee
#    ~~~~~~~~~~~~~
#
#    This is the base file of Kaylee client-side module.
#    It contains a small AJAX library used in a browser's
#    main JavaScript event loop.
#
#    :copyright: (c) 2013 by Zaur Nasibov.
#    :license: MIT, see LICENSE for more details.
*/


kl.ajax = function(url, method, data, success, fail) {
  var dl, key, req, val;
  if (success == null) {
    success = (function() {});
  }
  if (fail == null) {
    fail = (function() {});
  }
  req = new XMLHttpRequest();
  switch (method) {
    case "POST":
      if (!(data != null)) {
        data = {};
      }
      data = JSON.stringify(data);
      req.open('POST', url, true);
      req.setRequestHeader('Content-type', 'application/json; charset=utf-8');
      break;
    case "GET":
      if (data != null) {
        dl = [];
        for (key in data) {
          val = data[key];
          dl.push(key + '=' + encodeURIComponent(val));
        }
        url += '?' + dl.join('&');
      }
      req.open("GET", url, true);
  }
  req.onreadystatechange = function() {
    var response;
    if (req.readyState === 4) {
      if (req.status === 200 && (req.responseText != null)) {
        response = JSON.parse(req.responseText);
        if (response.error != null) {
          fail(response.error);
        } else {
          success(response);
        }
      } else if (!(response != null)) {
        fail('INVALID_STATE_ERR');
      } else {
        fail(response);
      }
    }
  };
  req.send(data);
};

kl.post = function(url, data, success, fail) {
  var _success;
  _success = function(resp_data) {
    if (resp_data.error != null) {
      return fail(resp_data.error);
    } else {
      return success(resp_data);
    }
  };
  kl.ajax(url, 'POST', data, _success, fail);
};

kl.get = function(url, data, success, fail) {
  var _success;
  if (arguments.length >= 2) {
    if (kl.util.is_function(data)) {
      fail = success;
      success = data;
      data = null;
    }
  }
  _success = function(resp_data) {
    if (resp_data.error != null) {
      return fail(resp_data.error);
    } else {
      return success(resp_data);
    }
  };
  kl.ajax(url, 'GET', data, _success, fail);
};

_dom_include = function(urls, success, fail) {
  var count, css, doc, failed, js, onerror, onload, sc, url, _i, _len;
  if (!(urls instanceof Array)) {
    urls = [urls];
  }
  count = urls.length;
  sc = 0;
  failed = false;
  for (_i = 0, _len = urls.length; _i < _len; _i++) {
    url = urls[_i];
    doc = document.getElementsByTagName('head')[0];
    onload = function() {
      sc += 1;
      if (sc === count && !failed) {
        return typeof success === "function" ? success() : void 0;
      }
    };
    onerror = function(msg) {
      failed = true;
      return typeof fail === "function" ? fail(msg) : void 0;
    };
    if (util.ends_with(url, '.js')) {
      js = document.createElement('script');
      js.setAttribute('type', 'text/javascript');
      js.setAttribute('src', url);
      js.onload = onload;
      js.onerror = onerror;
      doc.appendChild(js);
    } else if (util.ends_with(url, '.css')) {
      if (fail != null) {
        kl.exception('Kaylee is not able to invoke the fail()\
                    callback of kl.include(..) when loading stylesheets.');
        failed = true;
        return;
      }
      css = document.createElement("link");
      css.rel = 'stylesheet';
      css.type = 'text/css';
      css.href = url;
      css.onload = onload;
      doc.appendChild(css);
    }
  }
};

_worker_include = function(urls, success, fail) {
  var all_imported, error_message, url, _i, _len;
  if (!(urls instanceof Array)) {
    urls = [urls];
  }
  error_message = '';
  all_imported = true;
  for (_i = 0, _len = urls.length; _i < _len; _i++) {
    url = urls[_i];
    try {
      importScripts(url);
    } catch (error) {
      all_imported = false;
      error_message = "Error importing " + url + ": " + error.message;
      break;
    }
  }
  if (all_imported) {
    return typeof success === "function" ? success() : void 0;
  } else {
    return typeof fail === "function" ? fail(error_message) : void 0;
  }
};

kl.include = function(urls, success, fail) {
  if (typeof __DEFINE_WORKER !== "undefined" && __DEFINE_WORKER !== null) {
    return _worker_include(urls, success, fail);
  } else {
    return _dom_include(urls, success, fail);
  }
};

/*
#    klworker.coffee
#    ~~~~~~~~~~~~~~~
#
#    This is the base file of Kaylee client-side Web Worker module.
#    This module is used to execute the AUTO-mode projects.
#
#    :copyright: (c) 2013 by Zaur Nasibov.
#    :license: MIT, see LICENSE for more details.
*/


__DEFINE_WORKER = true;

pj = kl.pj;

on_worker_event = function(e) {
  var mdata, msg;
  msg = e.data.msg;
  mdata = e.data.data;
  switch (msg) {
    case 'import_project':
      return import_project(mdata);
    case 'process_task':
      return pj.process_task(mdata);
  }
};

addEventListener('message', on_worker_event, false);

kl.log = function(msg) {
  return post_message('__kl_log__', msg);
};

kl.error = function(msg) {
  return post_message('__kl_error__', msg);
};

post_message = function(msg, data) {
  if (data == null) {
    data = {};
  }
  return postMessage({
    'msg': msg,
    'data': data
  });
};

import_project = function(kwargs) {
  var _project_imported;
  kl.config = kwargs.kl_config;
  _project_imported = function() {
    kl.log('The project script has been imported');
    return pj.init(kwargs.app_config);
  };
  return kl.include(kwargs.app_config.__kl_project_script_url__, _project_imported, kl.error);
};

on_project_imported = function() {
  return post_message('project_imported');
};

on_task_completed = function(result) {
  return post_message('task_completed', result);
};

kl.project_imported = new Event(on_project_imported);

kl.task_completed = new Event(on_task_completed);
