EXPORTED_SYMBOLS = ["module"];
var module = function (app) {
var API = app.api;
const client_secret = "5E4DFBC278D1F82A3841A9FD";
const client_id = "696320";
const app_key = "CBABKLABABABABABA";
const default_date = "1981-20-05 23:50:45";
const urls = {
"domain": "http://odnoklassniki.ru",
"home": "",
"messages": "messages?_uaid=BrowserToolbar_Messages",
"notifications": "notifications?_uaid=BrowserToolbar_Notifications",
"guests": "guests?_uaid=BrowserToolbar_Guests",
"marks": "marks?_uaid=BrowserToolbar_PhotoMarks",
"bd": "profile/%UID%/friends",
"bd2": "dk?st.cmd=userFriendHoliday",
"bd-hd": "profile/%UID%/friends#st.cmd=userFriendHoliday"};
const redirectUrl = "http%3A%2F%2Fdesktop.yandex.ru%2Fmicroblogsodnoklassniki";
const accessTokenUrl = "http://odnoklassniki.ru/oauth/authorize?client_id=" + client_id + "&scope=VALUABLE%20ACCESS;MESSAGING&response_type=code&redirect_uri=";
const requestTokenUrl = "http://api.odnoklassniki.ru/oauth/token.do";
const apiUrl = "http://api.odnoklassniki.ru/fb.do";
const oauthWindowFeatures = "resizable=no,width=800,height=600,centerscreen";
const allowed_events = ["marks", "guests", "messages", "notifications"];
const ACTION_CONVERSATIONS = "ACTION-CONVERSATIONS";
const ACTION_BIRTHDAYS = "ACTION-BIRTHDAYS";
var Odnoklassniki = function Odnoklassniki() {
this.initialized = false;
this.isAuth = false;
this.update_interval = - 1;
this.updateTimer = null;
this.show_messages = false;
this.show_notifications = false;
this.show_guests = false;
this.show_marks = false;
this.show_bd = false;
this.counters = {
};
this.widgetInstaces = 0;
}
;
Odnoklassniki.prototype.InitModule = function InitModule() {
this.isAuth = this.GetIsAuth();
this.counters = app.settings.counters;
API.logger.debug("Odnoklassniki.InitModule: " + this.isAuth);
this.cookie = app.importModule("cookie.jsm");
this.cookie.init();
var $ = this;
var settingsListener = {
onSettingChange: function (name, value) {
$.OnSettingChange(name,value);
}
};
try {
API.Settings.observeChanges(settingsListener);
}
catch (e) {
API.logger.debug("Odnoklassniki.InitModule: settings listener already exists");
}

this.cookie.onlogout = function () {
if ($.isAuth)
{
$.Logout();
}

}
;
API.logger.debug("Odnoklassniki.InitModule: test cookie and try relogin");
if (this.isAuth)
{
this.Logout();
if (this.cookie.isAuth())
{
API.logger.debug("try relogin by cookie");
$.Auth(true);
}

}

var loginUrl = /^https?:\/\/www\.odnoklassniki\.ru\/https/;
this._reloginObserver = {
observe: function (subject, topic, data) {
if (! $.isAuth || "http-on-modify-request" !== topic)
{
return;
}

subject.QueryInterface(Components.interfaces.nsIHttpChannel);
var url = subject.URI.spec;
if (loginUrl.test(url) && subject.requestMethod == "POST")
{
API.logger.debug("Odnoklassniki._reloginObserver: url = " + url + ", requestMethod=" + subject.requestMethod);
$.Logout();
app.utils.setTimeout(function () {
$.Auth(true,true);
}
,2100);
}

}
};
this._observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
this._observerService.addObserver(this._reloginObserver,"http-on-modify-request",false);
}
;
Odnoklassniki.prototype.SaveIsAuth = function SaveIsAuth() {
try {
API.Settings.setValue("login",this.isAuth);
}
catch (e) {

}

}
;
Odnoklassniki.prototype.GetIsAuth = function GetIsAuth() {
return API.Settings.getValue("login") != "false";
}
;
Odnoklassniki.prototype.DeInitModule = function DeInitModule() {
try {
API.Settings.ignoreChanges();
}
catch (e) {

}

try {
this._observerService.removeObserver(this._reloginObserver,"http-on-modify-request");
}
catch (e) {

}

}
;
Odnoklassniki.prototype.OnSettingChange = function OnSettingChange(name, value) {
if (name == "update-interval")
{
this.update_interval = Number(value);
this.UpdateTimerInit();
}

}
;
Odnoklassniki.prototype.InitWidget = function InitWidget() {
if (this.initialized)
{
return;
}

this.dayStamp = this.GetDayStamp();
this.update_interval = Number(API.Settings.getValue("update-interval"));
this.UpdateTimerInit();
this.Update();
this.GetBirthdays();
this.initialized = true;
API.logger.debug("Odnoklassniki.InitWidget: " + this.update_interval);
}
;
Odnoklassniki.prototype.GetDayStamp = function GetDayStamp() {
var d = new Date();
var ds = d.getYear();
ds += "-" + d.getMonth();
ds += "-" + d.getDay();
return ds;
}
;
Odnoklassniki.prototype.UpdateTimerInit = function UpdateTimerInit() {
var $ = this;
if (this.updateTimerEnabled)
{
this.updateTimer.cancel();
this.updateTimerEnabled = false;
}

if (this.update_interval && this.update_interval > 0)
{
this.updateTimer = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer);
this.updateTimer.initWithCallback(function () {
$.Update($);
}
,this.update_interval * 1000 * 60,Components.interfaces.nsITimer.TYPE_REPEATING_SLACK);
this.updateTimerEnabled = true;
}

API.logger.debug("Odnoklassniki.UpdateTimerInit");
}
;
Odnoklassniki.prototype.Navigate = function Navigate(id, isUrl) {
Components.reportError("Navigate to : " + id);
if (isUrl)
{
API.Controls.navigateBrowser({
"url": id});
}
 else
{
var url = urls[id];
url = url.replace("%UID%",app.settings.uid);
API.Controls.navigateBrowser({
url: urls.domain + "/" + url});
}

}
;
Odnoklassniki.prototype.Logout = function Logout() {
API.logger.debug("Odnoklassniki.Logout");
app.ClearStorage();
this.isAuth = false;
this.SaveIsAuth();
app.notify("odnoklassniki-counters-updated","");
}
;
Odnoklassniki.prototype.RemoveCookies = function RemoveCookies() {
this.cookie.removeCookies();
}
;
Odnoklassniki.prototype.ConvertDate = function ConvertDate(str) {
var n = str.split("-");
var now = new Date();
var age = now.getFullYear() - Number(n[0]);
var month = Number(n[1]);
var day = Number(n[2]);
return {
"day": day,
"month": month,
"age": age};
}
;
Odnoklassniki.prototype.GetInfo = function GetUid(uids, action) {
var $ = this;
var callbacks = {
onLoad: function OnLoad(response) {
var info;
try {
info = JSON.parse(response);
}
catch (e) {
API.logger.debug("GetInfo parse error");
return;
}

if (action == ACTION_CONVERSATIONS)
{
for(var i in app.settings.conversations) {
var conv = app.settings.conversations[i];
if (conv && conv.friend_uid)
{
for(var j in info) {
if (info[j] && String(conv.friend_uid) == String(info[j].uid))
{
conv.name = info[j].name;
conv.gender = info[j].gender;
conv.url = info[j].url_profile;
delete conv.last_msg_time;
delete conv.last_view_time;
}

}

}

}

app.SaveStorage();
app.notify("odnoklassniki-conversations-updated","");
}
 else
if (action == ACTION_BIRTHDAYS)
{
for(var i in app.settings.bd) {
var bd = app.settings.bd[i];
if (bd.uid)
{
for(var j in info) {
if (info[j] && info[j].name && String(bd.uid) == String(info[j].uid))
{
bd.name = info[j].name;
bd.gender = info[j].gender;
bd.url = info[j].url_profile;
delete bd.sortParam;
}

}

}

}

app.SaveStorage();
app.notify("odnoklassniki-bd-updated","");
}

}
,
onError: function OnError(response) {

}
};
API.logger.debug("GetInfo uids: " + uids.join(","));
var ex_params = {
"fields": "uid,name,gender,url_profile",
"uids": uids.join(",")};
this.SendRequest("users.getInfo",callbacks,ex_params);
}
;
Odnoklassniki.prototype.GetBirthdays = function GetBirthdays() {
var $ = this;
app.settings.bd = [];
app.SaveStorage();
var callbacks = {
onLoad: function OnLoad(response) {
function sortFunc(a, b) {
return a.sortParam == b.sortParam ? 0 : a.sortParam > b.sortParam ? 1 : - 1;
}

var arr = [];
var uids = [];
try {
arr = JSON.parse(response);
for(var i in arr) {
arr[i].sortParam = arr[i].date.substr(5);
}

}
catch (e) {

}

if (arr && arr.length)
{
arr.sort(sortFunc);
for(var i in arr) {
if (arr[i].uid && arr[i].date)
{
uids.push(arr[i].uid);
arr[i].date = $.ConvertDate(arr[i].date);
arr[i].hd = true;
}

}

}

app.settings.bd = arr;
if (! app.settings.counters)
{
app.settings.counters = {
};
}

app.settings.counters.bd = arr.length;
API.logger.debug("GetBirthdays: " + response);
app.SaveStorage();
if (uids.length > 0)
{
$.GetInfo(uids,ACTION_BIRTHDAYS);
}
 else
{
app.notify("odnoklassniki-bd-updated","");
}

}
,
onError: function OnError(response) {

}
};
var ex_params = {
"future": false};
this.SendRequest("friends.getBirthdays",callbacks,ex_params);
}
;
Odnoklassniki.prototype.GetConversations = function GetConversations() {
var $ = this;
var callbacks = {
onLoad: function OnLoad(response) {
var conversations = [];
var conversations_all;
try {
conversations_all = JSON.parse(response);
}
catch (e) {

}

for(var i in conversations_all) {
var conv = conversations_all[i];
if (conv.new_msgs_count > 0)
{
conversations.push(conv);
}

}

app.settings.conversations = conversations;
var ts = app.settings.msg_last_check || default_date;
var uids = [];
for(var i in conversations) {
var conv = conversations[i];
if (conv.last_msg_time > ts)
{
ts = conv.last_msg_time;
}

if (conv.friend_uid)
{
uids.push(conv.friend_uid);
}

}

if (uids.length > 0)
{
$.GetInfo(uids,ACTION_CONVERSATIONS);
}

app.settings.msg_last_check = ts;
app.SaveStorage();
}
,
onError: function OnError(response) {

}
};
this.SendRequest("messages.getConversations",callbacks);
}
;
Odnoklassniki.prototype.ShowThrobber = function ShowThrobber(btn) {
btn = btn || "main";
app.notify("odnoklassniki-throbber",btn);
}
;
Odnoklassniki.prototype.Update = function Update(forceUpdate) {
var $ = this;
var callbacks = {
onLoad: function OnLoad(response) {
API.logger.debug("Update response: " + response);
var events;
try {
events = JSON.parse(response);
}
catch (e) {
API.logger.debug("Update. Unable to parse response: " + response);
}

if (events)
{
if (! app.settings.counters)
{
app.settings.counters = {
};
}

if (Number(events.error_code) == 102)
{
app.odnoklassniki.RefreshToken();
return;
}

for(var i in events) {
var event = events[i];
if (event && event.type && allowed_events.indexOf(event.type) != - 1)
{
app.settings.counters[event.type] = event.number;
}

if (! app.settings.uid && event && event.uid)
{
app.settings.uid = event.uid;
}

}

if (app.settings.counters.messages > 0)
{
$.GetConversations();
}

}

app.notify("odnoklassniki-counters-updated","");
app.SaveStorage();
}
,
onError: function OnError(response) {
app.notify("odnoklassniki-update-failed","");
API.logger.debug("Update error. Response: " + response);
}
};
this.SendRequest("events.get",callbacks);
if (app.settings.dayStamp != this.GetDayStamp() || forceUpdate)
{
this.GetBirthdays();
}

}
;
Odnoklassniki.prototype.SendRequest = function SendRequest(method, callbacks, ex_params) {
if (app.settings.refreshToken && app.settings.accessToken)
{
var url = apiUrl;
var data = {
};
data.application_key = app_key;
data.format = "json";
data.method = method;
if (ex_params)
{
for(var i in ex_params) {
data[i] = ex_params[i];
}

}

var paramsSign = app.utils.getUrlParams(data,false);
paramsSign = paramsSign.replace(/&/g,"");
data.sig = app.utils.md5(paramsSign + app.utils.md5(app.settings.accessToken + client_secret));
data.access_token = app.settings.accessToken;
var paramsPost = app.utils.getUrlParams(data,false);
var req = app.utils.Request(url,"POST",callbacks);
req.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
req.send(paramsPost);
}
 else
{
this.isAuth = false;
this.SaveIsAuth();
callbacks.onError();
}

}
;
Odnoklassniki.prototype.RefreshToken = function RefreshToken() {
var url = requestTokenUrl;
var req = app.utils.Request(url,"POST",{
onLoad: OnLoad,
onError: OnError});
req.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
var paramsPost = "refresh_token=" + app.settings.refreshToken;
paramsPost += "&" + "grant_type=refresh_token";
paramsPost += "&" + "client_id=" + client_id;
paramsPost += "&" + "client_secret=" + client_secret;
req.send(paramsPost);
function OnLoad(response) {
API.logger.debug("RefreshToken response: " + response);
var obj;
var updated = false;
try {
obj = JSON.parse(response);
if (obj.access_token)
{
app.settings.accessToken = obj.access_token;
app.SaveStorage();
updated = true;
}

}
catch (e) {

}

if (updated)
{
app.odnoklassniki.Update();
}
 else
{
app.odnoklassniki.Logout();
}

}

function OnError(response) {
API.logger.debug("RefreshToken error: " + response);
}

}
;
Odnoklassniki.prototype.Auth = function Auth(useAuthByCookie, retryAuthByDialog) {
var $ = this;
var oauthCallbacks = new app.utils.CallbackObject(function (code) {
getRequestToken(code);
}
, function () {
API.logger.debug("auth fail");
if (useAuthByCookie && retryAuthByDialog)
{
API.logger.debug("retry auth by dialog");
$.Auth();
}

}
);
function getRequestToken(code) {
API.logger.debug("getRequestToken: code=" + code);
var req = app.utils.Request(requestTokenUrl,"POST",{
onLoad: OnLoad,
onError: OnError});
var data;
data = "code=" + code;
data += "&redirect_uri=" + redirectUrl;
data += "&grant_type=authorization_code&client_id=" + client_id;
data += "&client_secret=" + client_secret;
req.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
req.send(data);
function OnLoad(response) {
API.logger.debug("getRequestToken response: " + response);
var obj;
try {
obj = JSON.parse(response);
}
catch (e) {
API.logger.debug("unable to parse response: " + response);
}

if (obj)
{
app.settings.refreshToken = obj.refresh_token;
app.settings.accessToken = obj.access_token;
$.isAuth = true;
$.SaveIsAuth();
app.SaveStorage();
$.Update(true);
}

}

function OnError(response) {
API.logger.debug("getRequestToken error. response: " + response);
}

}

if (useAuthByCookie)
{
authByCookie(oauthCallbacks);
}
 else
{
authByDialog(oauthCallbacks);
}

}
;
function getCodeParamsFromUrl(spec) {
var markerURL = "http://desktop.yandex.ru/microblogsodnoklassniki";
API.logger.debug("getCodeParamsFromUrl spec:" + spec);
if (spec.indexOf(markerURL) == 0)
{
return app.utils.ParseRequestString(spec.substr(spec.indexOf("?") + 1));
}
 else
{
return null;
}

}

function authByDialog(oauthCallbacks) {
var OAuthProgressListener = app.utils.createLocationListener(function (callbacks, aWebProgress, aRequest, aLocation) {
var params = getCodeParamsFromUrl(aLocation.spec);
if (params)
{
oauthWindow.close();
callbacks.success(params.code);
}

}
);
var oauthWindowArguments = {
url: accessTokenUrl + redirectUrl,
progressListener: new OAuthProgressListener(oauthCallbacks),
notifyMask: Components.interfaces.nsIWebProgress.NOTIFY_LOCATION,
onclose: function (event) {
API.logger.debug("CANCELED");
}
};
API.logger.debug("Odnoklassniki.Auth");
var oauthWindow = app.ui.openMicrobrowser(oauthWindowFeatures,oauthWindowArguments);
}

function authByCookie(oauthCallbacks) {
function getCode(response, xhr) {
var params = getCodeParamsFromUrl(xhr.channel.URI.spec);
if (params)
{
oauthCallbacks.success(params.code);
}
 else
{
oauthCallbacks.error();
}

}

var req = app.utils.Request(accessTokenUrl + redirectUrl,"GET",{
onLoad: getCode,
onError: getCode});
req.send();
}

return Odnoklassniki;
}
;
