var request = require("request");
var Service = require('../service');
var token = "";
var timeout = 1000;

//request.defaults({jar: true});

 function _toString (obj){
	var keys = Object.keys(obj);
	var str = "";

	for (var i = 0; i < keys.length; i++) {
		var key = keys[i];
		var val = obj[key];

        if(i <= 0)
			str += key+"="+val;
		else
			str += "&"+key+"="+val;
	}

	return str;
 }

function get_method(mathod, params, callback){
	var str_params = params != null ? _toString(params)+"&" : "";
	var url = 'https://api.vk.com/method/'+mathod+'?'+str_params+'access_token='+token;

    request.get({
        uri: url
    }, function(error, response, body){
		if(!error) {
			var res = JSON.parse(body);

			if(!res.error) {
                callback(res.response, null);
            } else {
                callback(null, res.error);
            }
		} else {
            callback(null, error);
        }
	})
}

function auth(params, callback){
    var opt = Service.extend({
        uri           : 'https://oauth.vk.com/access_token',
        client_id     : "",
        client_secret : "",
        redirect_uri  : "",
        code          : ""
    }, params || {});

	var url =  opt.uri +
              'client_id='     + opt.client_id     + '&' +
              'client_secret=' + opt.client_secret + '&' +
              'redirect_uri='  + opt.redirect_uri  + '&' +
              'code='          + opt.code;

    request.get({
        uri: url
    }, function(error, response, body){
        if (callback) callback.apply(null, arguments);
	})
}

function user(id) {
	var uid = id;
    var self = this;

	this.id = id;
	this.wall = new Wall(id);
	this.storage = new StorageVk(id);
	this.audio = new Audio(id);
	this.params_add_owner = function (params){
		if(params == null)
			params = {};
		params.user_id = uid;
		return params;
	};

	this.get = function(params, callback){
		params = this.params_add_owner(params);
		get_method("users.get", params, callback);
	};
	this.isAppUser = function(params, callback){
		params = this.params_add_owner(params);
		get_method("users.isAppUser", params, callback);
	};
	this.getFollowers = function(params, callback){
		params = this.params_add_owner(params);
		get_method("users.getFollowers", params, callback);
	};
	this.getSubscriptions = function(params, callback){
		params = this.params_add_owner(params);
		get_method("users.getSubscriptions", params, callback);
	};

	this.status = {
		get : function (callback){
			get_method("status.get", {user_id: uid}, callback);
		},
		set : function (status, callback, group_id){
			var params = {};
			if(typeof group_id !== "undefined")
				params.group_id = group_id;
			params.text = encodeURI(status);
			get_method("status.set", params, callback);
		}
	};

	this.friends = {
		params_add_owner : this.params_add_owner,
		get : function (params, callback){
			params = self.params_add_owner(params);
			get_method("friends.get", params, callback);
		},
		getOnline : function (params, callback){
			params = self.params_add_owner(params);
			get_method("friends.getOnline", params, callback);
		},
		add : function (params, callback){
			params = self.params_add_owner(params);
			get_method("friends.add", params, callback);
		},
		edit : function (params, callback){
			params = self.params_add_owner(params);
			get_method("friends.edit", params, callback);
		},
		"delete" : function (params, callback){
			params = self.params_add_owner(params);
			get_method("friends.delete", params, callback);
		},
		getLists : function (params, callback){
			params = self.params_add_owner(params);
			get_method("friends.getLists", params, callback);
		},
		areFriends : function (params, callback){
			if(params == null)
				params = {};
			params.user_ids = uid;
			get_method("friends.areFriends", params, callback);
		},
		search : function (params, callback){
			params = self.params_add_owner(params);
			get_method("friends.search", params, callback);
		}
	};
}

function Wall(domain_owner_id){
	var doId = [ typeof domain_owner_id === "number" ? "owner_id" : "domain", _toString(domain_owner_id) ];
    var self = this;

	this.params_add_owner = function (params){
		if(params == null)
			params = {};
		params[doId[0]] = doId[1];
		return params;
	};
	this.get = function (params, callback){
		params = this.params_add_owner(params);
		get_method("wall.get", params, callback);
	};
	this.search = function (params, callback){
		params = this.params_add_owner(params);
		get_method("wall.search", params, callback);
	};

	this.post = function (params, callback){
		params = self.params_add_owner(params);
		get_method("wall.post", params, callback);
	};
	this.getReposts = function (params, callback){
		params = self.params_add_owner(params);
		get_method("wall.getReposts", params, callback);
	};
	this.edit = function (params, callback){
		params = self.params_add_owner(params);
		get_method("wall.edit", params, callback);
	};
	this["delete"] = function (params, callback){
		params = self.params_add_owner(params);
		get_method("wall.delete", params, callback);
	};
	this.restore = function (params, callback){
		params = self.params_add_owner(params);
		get_method("wall.restore", params, callback);
	};
	this.pin = function (params, callback){
		params = self.params_add_owner(params);
		get_method("wall.pin", params, callback);
	};
	this.unpin = function (params, callback){
		params = self.params_add_owner(params);
		get_method("wall.unpin", params, callback);
	};
	this.getComments = function (params, callback){
		params = self.params_add_owner(params);
		get_method("wall.getComments", params, callback);
	};
	this.addComment = function (params, callback){
		params = self.params_add_owner(params);
		get_method("wall.addComment", params, callback);
	};
	this.editComment = function (params, callback){
		params = self.params_add_owner(params);
		get_method("wall.editComment", params, callback);
	};
	this.deleteComment = function (params, callback){
		params = self.params_add_owner(params);
		get_method("wall.deleteComment", params, callback);
	};
	this.restoreComment = function (params, callback){
		params = self.params_add_owner(params);
		get_method("wall.restoreComment", params, callback);
	};
	this.reportPost = function (params, callback){
		params = self.params_add_owner(params);
		get_method("wall.reportPost", params, callback);
	};
	this.reportComment = function (params, callback){
		params = self.params_add_owner(params);
		get_method("wall.reportComment", params, callback);
	};
}

function StorageVk(user_id){
    var self = this;

	this.params_add_owner = function (params){
		if (params == null) params = {};

		params.user_id = user_id;

		return params;
	};
	this.get = function(params, callback){
		params = self.params_add_owner(params);
		get_method("storage.get", params, callback);
	};
	this.set = function(params, callback){
		params = self.params_add_owner(params);
		get_method("storage.set", params, callback);
	};
	this.getKeys = function(params, callback){
		params = self.params_add_owner(params);
		get_method("storage.getKeys", params, callback);
	};
}

function Audio(user_id){
    var self = this;

	this.params_add_owner = function (params){
		if(params == null) params = {};

        params.owner_id = user_id;

        return params;
	};
	this.get = function (params, callback){
		params = self.params_add_owner(params);
		get_method("audio.get", params, callback);
	};
	this.add = function (params, callback){
		params = self.params_add_owner(params);
		get_method("audio.add", params, callback);
	};
	this["delete"] = function (params, callback){
		params = self.params_add_owner(params);
		get_method("audio.delete", params, callback);
	};
	this.edit = function (params, callback){
		params = self.params_add_owner(params);
		get_method("audio.edit", params, callback);
	};
	this.reorder = function (params, callback){
		params = self.params_add_owner(params);
		get_method("audio.reorder", params, callback);
	};
	this.restore = function (params, callback){
		params = self.params_add_owner(params);
		get_method("audio.restore", params, callback);
	};
	this.getAlbums = function (params, callback){
		params = self.params_add_owner(params);
		get_method("audio.getAlbums", params, callback);
	};
	this.getRecommendations = function (params, callback){
		if(params == null)
			params = {};
		params.user_id = user_id;
		get_method("audio.getRecommendations", params, callback);
	};
	this.getCount = function (params, callback){
		params = self.params_add_owner(params);
		get_method("audio.getCount", params, callback);
	};
}

module.exports = {
	init: function (tkn, tmot){
		timeout = typeof tmot !== "undefined" ? tmot : 1000;
		token = tkn;

        return this;
	}, 
	get_method : get_method,
    auth : auth,
	user : user,
	wall : Wall,
	storage: StorageVk,
	audio: Audio
};
