coreFramework.factory('SharedModel', function ($rootScope, $parse, $timeout, Language) {
    
    var languages = Language.getAll();
    var states = {
        PRISTINE: 'pristine',
        DIRTY: 'dirty',
        // VALID: 'valid',
        ERROR: 'error',
        // SUCCESS: 'success',
        LOADING: 'loading'
        
    };

    function getBlankList (config) {

        var list = [];
        var scope;
        var _syncTimeouts = {};

        for (var i = 0; i < languages.length; i++) {

            scope = (function (language) {

                var _state = states.PRISTINE;
                var _scope = $rootScope.$new(true);

                angular.extend(_scope, {
                    language: language,
                    headers: {
                        read: {
                            'X-Accept-Language': angular.lowercase(language.id),
                            'Accept-Language': angular.lowercase(language.id)
                        },
                        write: {
                            'X-Content-Language': angular.lowercase(language.id),
                            'Content-Language': angular.lowercase(language.id)
                        }
                    },
                    params: null,
                    data: {},
                    dataErrors: null,
                    form: {
                        is_valid: true,
                        is_dirty: false,
                        is_loading: false
                    },
                    promise: null
                });

                _scope.setDirty = function (is_dirty) {
                    $timeout(function () {
                        _scope.form.is_dirty = angular.isDefined(is_dirty) ? !!is_dirty : true;
                    });
                };

                _scope.addSync = function (param) {
                    
                    _scope.$watchCollection('data.' + param, function (value) {
                        $timeout.cancel($parse(param)(_syncTimeouts));
                        $parse(param).assign(_syncTimeouts, $timeout(function () {
                            list.filter(function (item) {
                                return item.$id != _scope.$id;
                            }).forEach(function (item) {
                                $parse(param).assign(item.data, angular.copy(value));
                                $parse('is_dirty').assign(item.form, angular.copy(_scope.form.is_dirty));
                            });
                        }));
                    }, true);
                };

                Object.defineProperties(_scope, {
                    state: {
                        get: function () {
                            if (_scope.form.is_loading) {
                                return states.LOADING;
                            } else if (_scope.form.is_dirty) {
                                if (_scope.form.is_valid) {
                                    return states.DIRTY;
                                } else {
                                    return states.ERROR;
                                }
                            } else {
                                return states.PRISTINE;
                            }
                        },
                        enumerable: true
                    },
                });

                return _scope;

            })(languages[i]);

            list.push(scope);

        }

        return list;

    };

    return function (config) {

        var _self = {};
        var _config = config || {};
        var _list = getBlankList(_config);
        var _activeIndex = 0;
        var _skipParams = [];
        
        Object.defineProperties(_self, {
            list: {
                get: function () {
                    return _list;
                },
                enumerable: true
            },
            activeIndex: {
                get: function () {
                    return _activeIndex;
                },
                set: function (index) {
                    _activeIndex = index;
                },
                enumerable: true
            },
            activeModel: {
                get: function () {
                    return _list[_activeIndex];
                },
                enumerable: true
            },
        });

        _self.states = states;

        _self.addSync = function (param) {
            angular.forEach(_list, function (item) {
                item.addSync(param);
            });
        };
        _self.addSkip = function (param) {
            _skipParams.push(param);
        };
        _self.copyFrom = function (index) {
            if (index == _activeIndex) {
                return;
            }
            if (!_list[_activeIndex].form.is_dirty || confirm('Are you sure you want to overwrite all ' + _list[_activeIndex].language.title + ' content with the ' + _list[index].language.title + ' one?')) {
                var skipped = {};
                _skipParams.forEach(function (item) {
                    $parse(item).assign(skipped, $parse(item)(_list[_activeIndex].data))
                });
                angular.copy(_list[index].data, _list[_activeIndex].data);
                angular.extend(_list[_activeIndex].data, skipped);
                _list[_activeIndex].form.is_dirty = true;
                _list[_activeIndex].form.is_valid = _list[index].form.is_valid;
            }
        };
        _self.setLanguage = function (id) {

            for (var i = 0; i < languages.length; i++) {
                if (angular.lowercase(id) === angular.lowercase(languages[i].id)) {
                    _activeIndex = i;
                    break;
                }
            }
            
        };

        return _self;

    };
    
});