'use strict';

(function() {
    var module = angular.module('hermes', []);

    module.provider('Hermes', function() {
        var defaultConfiguration;

        var Configuration = function() {
            this.baseUrl = '';
            this.requestBuilderHooks = [];
            this.responseErrorHooks = [];

            this.setBaseUrl = function(url) {
                this.baseUrl = url;

                if (this.baseUrl[this.baseUrl.length - 1] == '/') {
                    this.baseUrl = this.baseUrl.substr(0, this.baseUrl.length - 1);
                }
            };
        };

        var Element = function(service, baseUrl, name) {
            var methods = ['get', 'put', 'post', 'patch', 'delete'];
            var url = baseUrl + '/' + name;

            _.each(methods, function(method) {
                this[method] = function(config) {
                    return service.sendRequest(method, url, config || {});
                };
            }, this);

            this.element = function(name) {
                return new Element(service, url, name);
            };
        };

        var createService = function($q, $http, configuration) {
            var service = {};

            service.configuration = configuration;
            service.mockData = {};

            service.processRequest = function(requestData) {
                var self = this;
                var request = _.extend({}, requestData.request);
                var deferIt = $q.defer();
                var skipHttp = false;

                _.each(this.configuration.requestBuilderHooks, function(hook) {
                    request = hook(request);
                }, this);

                deferIt.promise.then(function(data, status, headers, config) {
                    requestData.result.resolve(data, status, headers);
                }, function(data, status, headers, config) {
                    var waiter;

                    _.each(self.configuration.responseErrorHooks, function(hook) {
                        var result = hook(data, status, headers, request);

                        if (_.isObject(result)) {
                            waiter = result;
                        }
                    }, self);

                    if (waiter != undefined) {
                        waiter.then(function() {
                            self.processRequest(requestData);
                        });
                    } else {
                        requestData.result.reject({
                            data: data,
                            status: status,
                            headers: headers
                        });
                    }
                });

                if (this.mockImpl
                    && this.mockData[requestData.request.url] != undefined
                    && this.mockData[requestData.request.url][requestData.request.method] != undefined) {
                    var result = this.mockImpl.processMock(this.mockData[requestData.request.url][requestData.request.method], request);

                    if (result != undefined) {
                        if (result.status == 200) {
                            deferIt.resolve(result.data, result.status, result.headers, request);
                        } else {
                            deferIt.reject(result.data, result.status, result.headers, request);
                        }

                        skipHttp = true;
                    }
                }

                if (!skipHttp) {
                    $http(request).success(function (data, status, headers, config) {
                        deferIt.resolve(data, status, headers, config);
                    }).error(function (data, status, headers, config) {
                        deferIt.reject(data, status, headers, config);
                    });
                }
            };

            service.sendRequest = function(method, url, config) {
                var deferred = $q.defer();

                var request = _.merge({
                    url: url,
                    method: method,
                    headers: {},
                    params: {},
                    cache: false
                }, config);

                var requestData = {
                    request: request,
                    result: deferred
                };

                this.processRequest(requestData);

                return deferred.promise;
            };

            service.mockCall = function(method, url, id) {
                if (this.mockData[url] == undefined) {
                    this.mockData[url] = {};
                }

                if (this.mockData[url][method] != undefined) {
                    return this.mockData[url][method];
                }

                this.mockData[url][method] = id;
            };

            service.element = function(name) {
                return new Element(this, configuration.baseUrl, name);
            };

            return service;
        };

        defaultConfiguration = new Configuration();

        this.Configuration = Configuration;
        this.defaultConfiguration = defaultConfiguration;
        this.createService = createService;

        this.$get = function($q, $http) {
            return createService($q, $http, defaultConfiguration);
        };
    });

})();

@@ -1727,33 +1727,8 @@
 data
-, status, headers, config
 ) %7B%0A
@@ -1774,34 +1774,44 @@
 resolve(data
-, 
+.data, data.
 status, 
 headers);%0A  
@@ -1794,24 +1794,29 @@
 ata.status, 
+data.
 headers);%0A  
@@ -1849,33 +1849,8 @@
 data
-, status, headers, config
 ) %7B%0A
@@ -2007,34 +2007,44 @@
  = hook(data
-, 
+.data, data.
 status, 
 headers, req
@@ -2023,32 +2023,37 @@
 a, data.status, 
+data.
 headers, request
@@ -2509,16 +2509,21 @@
   data: 
+data.
 data,%0A  
@@ -2556,16 +2556,21 @@
 status: 
+data.
 status,%0A
@@ -2606,16 +2606,21 @@
 eaders: 
+data.
 headers%0A
@@ -3190,632 +3190,1354 @@
 lve(
-result.data, result.status, result.headers, request);%0A                        %7D else %7B%0A                            deferIt.reject(result.data, result.status, result.headers, request);%0A                        %7D%0A%0A                        skipHttp = true;%0A                    %7D%0A                %7D%0A%0A                if (!skipHttp) %7B%0A                    $http(request).success(function (data, status, headers, config) %7B%0A                        deferIt.resolve(data, status, headers, config);%0A                    %7D).error(function (data, status, headers, config) %7B%0A                        deferIt.reject(data, status, headers, config
+%7B%0A                                data:result.data,%0A                                status: result.status,%0A                                headers: result.headers,%0A                                config: request%0A                            %7D);%0A                        %7D else %7B%0A                            deferIt.reject(%7B%0A                                data:result.data,%0A                                status: result.status,%0A                                headers: result.headers,%0A                                config: request%0A                            %7D);%0A                        %7D%0A%0A                        skipHttp = true;%0A                    %7D%0A                %7D%0A%0A                if (!skipHttp) %7B%0A                    $http(request).success(function (data, status, headers, config) %7B%0A                        deferIt.resolve(%7B%0A                            data: data,%0A                            status: status,%0A                            headers: headers,%0A                            config: config%0A                        %7D);%0A                    %7D).error(function (data, status, headers, config) %7B%0A                        deferIt.reject(%7B%0A                            data: data,%0A                            status: status,%0A                            headers: headers,%0A                            config: config%0A                        %7D
 );%0A 

Fix $q misuse.