coreFramework.factory('DataService', function (Restangular, Message, AssignmentService, $timeout) {

    return function(api, type, origin) {

        // private
        var _api = api;
        var _type = type;
        var _origin = origin;
        var _query = '';
        var _data = {};
        var _count = 0;
        var _options = {};
        var _methods = ['get', 'getList'];
        var _dummyData = [];
        var _isLoading = false;

        // public
        this.api = api;
        this.type = type;
        Object.defineProperties(this, {
            api: {
                get: function () {
                    return _api || '';
                },
                set: function (value) {
                    _api = value;
                },
                enumerable: true
            },
            type: {
                get: function () {
                    return _type || '';
                },
                set: function (value) {
                    _options['origin'] = _origin;
                    _type = value;
                },
                enumerable: true
            },
            origin: {
                get: function () {
                    return _origin || '';
                },
                set: function (value) {
                    _options['origin'] = value;
                    _origin = value;
                },
                enumerable: true
            },
            query: {
                get: function () {
                    return _options['query'] || '';
                },
                set: function (value) {
                    _options['query'] = value;
                },
                enumerable: true
            }
        });

        // public read only
        Object.defineProperties(this, {
            data: {
                get: function() {
                    if (_options.offset < _dummyData.length) {
                        return _dummyData.concat(_data).slice(_options.offset, _options.limit);
                    }
                    return _data;
                },
                enumerable: true
            },
            dummyData: {
                get: function() {
                    return _dummyData;
                },
                enumerable: true
            },
            count: {
                get: function() {
                    return parseInt(_count, 10) + parseInt(_dummyData.length, 10);
                },
                enumerable: true
            },
            isLoading: {
                get: function() {
                    return _isLoading;
                },
                enumerable: true
            }
        });

        function call(method, params) {

            var element = '';
            var queryParts = [];

            if (!angular.isDefined(method)) {
                method = 'get';
            }

            if (!angular.isDefined(params)) {
                params = {};
            } else {
                if (!isNaN(parseInt(params))) {
                    element = params + '/';
                    params = {};
                }
            }

            if (params !== null) {
                if (angular.isDefined(params.origin)) {
                    if (params.origin != '') {
                        queryParts.push('"origin":"' + params.origin + '"');
                    }
                    delete params.origin;
                } else if (angular.isDefined(_options['origin'])) {
                    if (_options['origin'] != '') {
                        queryParts.push('"origin":"' + _options['origin'] + '"');
                    }
                }
                if (angular.isDefined(params.query)) {
                    queryParts.push(params.query);
                    delete params.query;
                } else if (angular.isDefined(_options['query'])) {
                    queryParts.push(_options['query']);
                }

                params.query = queryParts.join(' ').trim();
                if (params.query == '') {
                    delete params.query;
                }

                angular.forEach(_options, function(value, key){
                    if (key == 'origin' || key == 'query' || this[key]) {

                    } else {
                        this[key] = value;
                    }
                }, params);

            }

            params.offset = parseInt(params.offset, 10) || 0;

            if (_options.origin == AssignmentService.STATE || _options.origin == AssignmentService.STATIC) {
                console.log(_options['query']);
                var data = AssignmentService.getList(_type);
                if (_options['query']) {
                    var filtered = [];
                    angular.forEach(data, function(item) {
                        console.log(item);
                        if ((item.title || item.name || item.type).toLowerCase().indexOf(_options['query'].toLowerCase()) >= 0) {
                            filtered.push(item);
                        }
                    });
                    data = filtered;
                }
                $timeout(function() {
                    _count = data.length;
                    _data = data.slice(params.offset, params.offset + parseInt(params.limit, 10));
                }, 0);
                return;
            }

            params.offset = parseInt(params.offset, 10) > _dummyData.length ? parseInt(params.offset, 10) - _dummyData.length : 0;
            _isLoading = true;

            return Restangular.oneUrl('data', _api + element)[method](params).then(function (response) {
                switch (method) {
                    case 'get':
                    case 'getList':
                        if (angular.isDefined(response.headers()['x-metadata-total'])) {
                            _count = response.headers()['x-metadata-total'];
                        }
                        for (var i = 0; i < _dummyData.length; i++) {
                            if (_dummyData[i].progress == 100) {
                                _dummyData.splice(i, 1);
                                i--;
                            }
                        }
                        _data = response.data.originalElement;
                        break;
                }
                _isLoading = false;
            }, function (errors) {
                Message.send('Error!', 'error');
                _isLoading = false;
            });

        }

        this.reset = function() {

            angular.forEach(_options, function(value, key){
                delete this[key];
            }, _options);
            _options['order'] = 'created_at desc';
            _options['origin'] = _origin;
            _dummyData = [];

        };

        this.getOption = function(key) {
            return _options[key];
        };
        this.setOption = function(key, value) {
            if (angular.isDefined(value)) {
                _options[key] = value;
            } else {
                delete _options[key];
            }
        };

        this.set = function (data) {
            _data = data;
        };

        // init
        this.reset();
        angular.forEach(_methods, function(value, key){
            this[value] = function(params) {
                return call(value, params);
            };
        }, this);

    };

});
