EXPORTED_SYMBOLS = ["module"];
var module = function (application) {
var log = function (message) {
application.logger.trace("[VK Auth] " + message);
}
;
var api = application.api;
var VKAuth = function () {
this._userId = 0;
this._accessToken = "";
this._expirationTime = 0;
this.init();
}
;
VKAuth.prototype = {
constructor: VKAuth,
_getURLParamsString: function (params) {
var param;
return [param + "=" + encodeURIComponent(params[param]) for (param in params)].join("&");
}
,
_getCurrentTimestamp: function () {
var timestamp = Math.floor((new Date()).getTime() / 1000);
return timestamp;
}
,
_cache: null,
init: function () {
var Cache = application.Cache;
var cache = this._cache = new Cache("vk.auth.json");
this._accessToken = cache.get("access_token") || "";
this._expirationTime = Number(cache.get("expiration_time")) || 0;
this._userId = Number(cache.get("user_id")) || 0;
var auth = this;
var mailman = application.mailman;
mailman.addSubscriber({
subject: "please-get-user-id",
subscriber: {
receive: function () {
mailman.send({
subject: "user-id",
body: auth._userId});
}
}});
mailman.addSubscriber({
subject: "please-check-auth",
subscriber: {
receive: function () {
auth.checkAccessToken(function () {
mailman.send("auth-granted");
}
);
}
}});
mailman.addSubscriber({
subject: "please-start-auth",
subscriber: {
receive: function () {
auth._startAuth(function () {
mailman.send({
subject: "please-update",
body: "all"});
}
);
}
}});
}
,
destroy: function () {
var cache = this._cache;
cache.put("access_token",this._accessToken);
cache.put("expiration_time",String(this._expirationTime));
cache.put("user_id",String(this._userId));
}
,
checkAccessToken: function (success) {
if (this._accessTokenIsValid())
{
success();
}
 else
{
this._updateAccessToken(success);
}

}
,
resetAccessToken: function () {
this._accessToken = "";
}
,
authorizedRequest: function (success, error) {
if (this._accessTokenIsValid())
{
success(this._accessToken);
}
 else
{
this._updateAccessToken(success);
}

}
,
logout: function () {
this._accessToken = "";
if (this._cache)
{
this._cache.clear();
}

this.ajax.getJSON(this._logoutURL,"",function () {

}
);
var mailman = application.mailman;
mailman.send("auth-lost");
}
,
_ajax: null,
get ajax() {
if (null == this._ajax)
{
this._ajax = new application.Ajax();
}

return this._ajax;
}
,
_accessTokenIsValid: function () {
var isEmpty = "" === this._accessToken;
var isExpired = this._getCurrentTimestamp() > this._expirationTime;
return ! isEmpty && ! isExpired;
}
,
_updateAccessToken: function (success) {
var url = this._getAuthURL();
var auth = this;
this.ajax.xhr({
url: url,
type: "GET",
success: function (data, textStatus, request) {
var url = request.channel.URI.spec;
var isRedirected = auth._isRedirectUrl(url);
if (isRedirected)
{
auth._handleAuthRedirect(url,success);
}

}
,
error: function () {
log("updateAccessToken failed.");
}
});
}
,
get _authURLRoot() {
return "http://oauth.vk.com/oauth/authorize?";
}
,
get _authRedirectURLvk() {
return "http://api.vk.com/blank.html";
}
,
get _authRedirectURLvkontakte() {
return "http://api.vkontakte.ru/blank.html";
}
,
get _logoutURL() {
return "http://oauth.vk.com/oauth/logout";
}
,
_getAuthURL: function () {
const AUTH_URL_ROOT = this._authURLRoot;
const REDIRECT_URL = this._authRedirectURLvk;
const APP_ID = 2438613;
const DISPLAY_TYPE = "popup";
const SCOPE = "audio,friends,messages,notes,video";
const RESPONSE_TYPE = "token";
var params = {
__proto__: null};
params.client_id = APP_ID;
params.scope = SCOPE;
params.redirect_uri = REDIRECT_URL;
params.display = DISPLAY_TYPE;
params.response_type = RESPONSE_TYPE;
var url = AUTH_URL_ROOT + this._getURLParamsString(params);
log("auth url: " + url);
return url;
}
,
_authWindow: null,
_authWindowPath: "",
_startAuth: function (success) {
var auth = this;
var authWindow = this._authWindow;
if (authWindow !== null && ! authWindow.closed)
{
authWindow.focus();
return;
}

const authWindowName = "yb-vkplayer-auth";
const AUTH_URL_ROOT = this._authURLRoot;
const REDIRECT_URL = this._authRedirectURL;
var __windowWatcher = null;
var getWindowWatcher = function () {
return __windowWatcher ? __windowWatcher : (__windowWatcher = Components.classes["@mozilla.org/embedcomp/window-watcher;1"].getService(Components.interfaces.nsIWindowWatcher));
}
;
var windowWatcher = getWindowWatcher();
var authPagePath = this._getAuthURL();
var authWindowPath = this._authWindowPath ? this._authWindowPath : (this._authWindowPath = api.Package.resolvePath("content/authWindow/window.xul"));
var features = "chrome,centerscreen,width=620,height=360";
authWindow = windowWatcher.openWindow(null,authWindowPath,authWindowName,features,null);
var timer = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer);
authWindow.addEventListener("load",function () {
var browser = authWindow.browser;
const STATE_START = Components.interfaces.nsIWebProgressListener.STATE_START;
const STATE_STOP = Components.interfaces.nsIWebProgressListener.STATE_STOP;
const STATE_IS_WINDOW = Components.interfaces.nsIWebProgressListener.STATE_IS_WINDOW;
browser.addProgressListener(auth._listener = {
onLocationChange: function (aProgress, aRequest, aURI) {
if (! aURI || ! aURI.spec)
{
return;
}

var url = aURI.spec;
if (auth._isRedirectUrl(url))
{
aRequest.cancel(Components.results.NS_BINDING_ABORTED);
authWindow.close();
auth._handleAuthRedirect(url,success);
}

}
,
onStateChange: function (aWebProgress, aRequest, aFlag, aStatus) {
if (aFlag & STATE_STOP && aFlag & STATE_IS_WINDOW)
{
if (0 !== aStatus)
{
return;
}

if (! aWebProgress || ! aWebProgress.DOMWindow || ! aWebProgress.DOMWindow.document)
{
return;
}

let document = aWebProgress.DOMWindow.document;
authWindow.api.contentIsLoaded = true;
authWindow.api.setWindowTitle(document.title);
}

}
,
onProgressChange: function () {

}
,
onStatusChange: function () {

}
,
onSecurityChange: function () {

}
,
QueryInterface: function (aIID) {
if (aIID.equals(Components.interfaces.nsIWebProgressListener) || aIID.equals(Components.interfaces.nsISupportsWeakReference) || aIID.equals(Components.interfaces.nsISupports))
{
return this;
}

throw Components.results.NS_NOINTERFACE;
}
});
browser.loadURI(authPagePath);
}
,false);
}
,
_isRedirectUrl: function (url) {
return url.indexOf(this._authRedirectURLvk) == 0 || url.indexOf(this._authRedirectURLvkontakte) == 0;
}
,
_handleAuthRedirect: function (_url, callback) {
var url = _url.replace("#","?");
var paramsPairs = url.split("?")[1].split("&");
var params = {
__proto__: null};
for (let i = 0, len = paramsPairs.length;i < len;i++) {
let pair = paramsPairs[i];
let array = pair.split("=");
let name = array[0];
let value = array[1];
params[name] = value;
}

log("Response params:\n" + JSON.stringify(params));
if ("undefined" !== typeof params.error)
{
log("Authorization error has occurred.");
log("Error reason: " + params.error_reason);
log("Error description: " + params.error_description.replace("%20"," ","g"));
return;
}

this._userId = params.user_id;
this._accessToken = String(params.access_token);
this._expirationTime = this._getCurrentTimestamp() + Number(params.expires_in);
log("Access token received " + this._accessToken);
var mailman = application.mailman;
mailman.send("auth-granted");
mailman.send({
subject: "user-id",
body: this._userId});
if ("function" == typeof callback)
{
callback(this._accessToken);
}

}
};
return VKAuth;
}
;
