(function () {
    "use strict";

    angular.module('hip').service('bip', function ($http, $q) {
        this.events = new EventSource();
        this.token = undefined;

        this.getToken = function () {
            return this.token;
        };

        this.setToken = function (token) {
            // Set the token in a cookie
            if (token) {
                var expiry = new Date(new Date().getTime() + Token.decode(token).duration()).toUTCString();
                document.cookie = "Authorization=Bearer " + token + "; expires=" + expiry + ";";
            } else {
                document.cookie = "Authorization=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
            }

            this.token = token;

            this.events.emit('token', [this.token, token], this);
        };

        this.getUserIdFromToken = function () {
            if (!this.token) return;
            var decoded = Token.decode(this.token);
            return parseInt(decoded.payload["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"]);
        };

        this.getHttpConfiguration = function () {
            if (this.token && Token.decode(this.token).duration() > 5000) {
                return { headers: { 'Authorization': 'Bearer ' + this.token } };
            } else {
                return {};
            }
        };

        this.get = function (url) {
            return $http.get(url, this.getHttpConfiguration()).then(this.success).catch(this.error);
        };

        this.post = function (url, data) {
            return $http.post(url, data, this.getHttpConfiguration()).then(this.success).catch(this.error);
        };

        this.put = function (url, data) {
            return $http.put(url, data, this.getHttpConfiguration()).then(this.success).catch(this.error);
        };

        this.delete = function (url) {
            return $http.delete(url, this.getHttpConfiguration()).then(this.success).catch(this.error);
        };

        this.upload = function (url, data) {
            var configuration = this.getHttpConfiguration();
            configuration.headers['Content-Type'] = undefined;
            configuration.transformRequest = angular.identity;
            return $http.post(url, data, configuration).then(this.success).catch(this.error);
        };

        this.success = function (response) {
            return response.data;
        };

        var self = this;
        this.error = function (response) {
            self.events.emit('error', arguments, self);
            return $q.reject(response);
        };

        this.onToken = function (listener) {
            this.events.on('token', listener);
        };

        this.onError = function (listener) {
            this.events.on('error', listener);
        };
    });
})();
