"use strict";
var EXPORTED_SYMBOLS = ["Utils"];
Cu.import("resource://gre/modules/Services.jsm");
var {Observers: Observers} = require("observers");
[["UUID_GENERATOR", "@mozilla.org/uuid-generator;1", "nsIUUIDGenerator"]].forEach(function ([name, contract, iface]) {
XPCOMUtils.defineLazyServiceGetter(this,name,contract,iface);
}
,this);
var Utils = {
sendRequest: function Utils_sendRequest(aURL, aDetails) {
var request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
if ("background" in aDetails)
request.mozBackgroundRequest = aDetails.background;
var method = aDetails.method || "GET";
request.open(method,aURL,true);
if (aDetails.bypassCache)
request.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE;
if (aDetails.anonymous)
request.channel.loadFlags |= Ci.nsIRequest.LOAD_ANONYMOUS;
if (aDetails.referrer)
request.setRequestHeader("Referrer",aDetails.referrer);
if (aDetails.timeout)
request.timeout = aDetails.timeout;
if (aDetails.data)
{
request.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
request.setRequestHeader("Connection","close");
}

if (aDetails.responseType)
request.responseType = aDetails.responseType;
if (aDetails.headers)
{
for(let [headerName, headerValue] in Iterator(aDetails.headers)) {
request.setRequestHeader(headerName,headerValue);
}

}

if (aDetails.callback)
{
let target = request.QueryInterface(Ci.nsIDOMEventTarget);
target.addEventListener("load",aDetails.callback,false);
target.addEventListener("error",aDetails.callback,false);
target.addEventListener("timeout",aDetails.callback,false);
}

if (aDetails.data instanceof Uint8Array)
aDetails.data = aDetails.data.buffer;
request.send(aDetails.data || null);
return request;
}
,
notify: function Utils_notify(prefix) {
return function NotifyMaker(name, data, func) {
var thisArg = this;
var notify = function notify(state, subject) {
var message = prefix + name + ":" + state;
NativeAPI.logger.trace("Event: " + message);
Observers.notify(message,subject,data);
}
;
return (function WrappedNotify() {
try {
notify("start",null);
let ret = func && func.call(thisArg);
notify("finish",ret);
return ret;
}
catch (ex) {
notify("error",ex);
throw ex;
}

}
)();
}
;
}
,
namedTimer: function Utils_namedTimer(callback, wait, thisObj, name) {
if (! thisObj || ! name)
{
throw new Error("You must provide both an object and a property name for the timer!");
}

if (name in thisObj && thisObj[name] instanceof Ci.nsITimer)
{
thisObj[name].delay = wait;
return;
}

var timer = Object.create(Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer));
timer.clear = function timerClear() {
thisObj[name] = null;
timer.cancel();
}
;
timer.initWithCallback({
notify: function notify() {
timer.clear();
callback.call(thisObj,timer);
}
},wait,timer.TYPE_ONE_SHOT);
return thisObj[name] = timer;
}
,
nextTick: function Utils_nextTick(callback, thisObj) {
if (thisObj)
callback = callback.bind(thisObj);
Services.tm.currentThread.dispatch(callback,Ci.nsIThread.DISPATCH_NORMAL);
}
,
databaseWrapper: function Utils_databaseWrapper(dbConnection) {
var dbWrapper = NativeAPI.Database.createInstance();
dbWrapper.connection = dbConnection;
return dbWrapper;
}
,
generateUUIDString: function Utils_generateUUIDString() UUID_GENERATOR.generateUUID().toString().substr(1,8),
throttle: function Utils_throttle(callback, threshhold) {
if (typeof threshhold !== "number" || threshhold <= 0)
throw new RangeError("Threshhold must be a positive number");
var last = 0;
var deferTimer;
var throttle = function throttle() {
var now = Date.now();
var args = arguments;
var _callback = function _callback() {
last = now;
callback.apply(null,args);
}
;
throttle.cancel();
var diff = Math.max(0,threshhold - Math.abs(now - last));
if (last && diff)
{
deferTimer = new NativeAPI.SysUtils.Timer(_callback, diff);
}
 else
{
_callback();
}

}
;
throttle.cancel = function throttle_cancel() {
if (! deferTimer)
return;
deferTimer.cancel();
deferTimer = null;
}
;
return throttle;
}
,
escapeTag: function Utils_escapeTag(str) {
return str.split("").map(function (ch) {
if (ch.charCodeAt(0) > 127 || ch.charCodeAt(0) <= 32)
{
return encodeURIComponent(ch);
}

;
return ch.replace(/["#%:<>\?\[\\\]^`{|} ]/,function (c) {
return encodeURIComponent(c);
}
);
}
).join("");
}
};
