(function(window) {
    // Use the correct document accordingly with window argument (sandbox)
    var document = window.document;

    var EFS = {
        version: '1.0',
        isDomReady: false,

        constants: {
            ids: {
                overlay: 'overlay',
                container: 'overlay_container'
            },
            classes: {
                showWindow: 'showWindow',
                showOverlay: 'showOverlay',
                showMore: 'show_more',
                closeOverlay: 'closeOverlay',
                maskLoading: 'loading',
                maskText: 'loading_txt',
                formFocused: 'focused',
                formRemaining: 'remaining',
                formExpandable: 'expandable',
                formNoSend: 'noSend',
                formNoSubmit: 'noSubmit',
                formAjax: 'fajax',
                inputSelect: 'selectAll',
                inputAutofocus: 'autofocus',
                styleSelect: 'styleSelect',
                ajax: 'hajax'
            }
        },
        regExp: {
            required: /[^.*]/,
            username: /^[a-zA-Z0-9_]{1,16}$/,
            password: /^.{6}.*/,
//            email: /^[a-z0-9._%-]+@[a-z0-9.-]+\.[a-z]{2,4}$/,
            email: /^([^@]+)@([^\s@.]([^\s@.]*\.[^\s@.]+)+)$/,
            validate: /^validate(\[.+\])$/,
            number: /[^.*]/,
            lajax: /^lajax(\[.+\])$/
        },
        actions: {
            commands: {
                inject: 'INJECT',
                append: 'APPEND',
                replaces: 'REPLACES',
                deleted: 'DELETED',
                inserts: 'INSERTS'
            },
            where: {
                top: 'top',
                bottom: 'bottom',
                after: 'after',
                before: 'before'
            },
            callbacks: {
                reloadNotice: 'reloadNotice',
                reloadThemePacks: 'reloadThemePacks'
            }
        },
        ajax: function(options, callback, target) {
            if (target !== undefined) {
                try {
                    target.submit.disabled = true;
                } catch (err) {
                }

                var mask = this.mask.show.init(target, 'js.form.loading');
                var maskError = this.mask.error.init(target, 'js.form.try_again');
            }

            var settings = {
                'url': null,
                'method': target !== undefined ? (target.getProperty('method') !== null ? target.getProperty('method') : 'GET') : 'GET',
                'data': {
                    'url': window.location.href
                },
                'link': 'ignore',
                'async': true,
                'encoding': 'utf-8',
                'evalScripts': false,
                'evalResponse': false,
                'emulation': true,
                'urlEncoded': true,
                'noCache': true,
                'onComplete': function() {
                    if (target !== undefined) {
                        try {
                            target.submit.disabled = false;
                        } catch (err) {
                        }
                    }
                },
                'onSuccess': function(response) {
                    EFSHelpers.urlHelper.response(response);

                    var doActions = function(response) {
                        if (response.hash !== null) {
                            try {
                                EFSHelpers.urlHelper.setHash(response.hash);
                            } catch (err) {
                            }
                        }

                        if (response.render !== null) {
                            try {
                                this.elements.create(response.render);
                            } catch (err) {
                            }
                        }

                        if (response.highlight !== null) {
                            try {
                                this.elements.highlight(response.highlight);
                            } catch (err) {
                            }
                        }

                        if (target !== undefined) {
                            mask.hide();
                            maskError.hide();
                        }

                        try {
                            if (response.status === true && (response.closeOverlay === undefined || response.closeOverlay === true)) {
                                this.showOverlay.close();
                            }
                        }
                        catch (err) {
                        }

                        if (response.overlay !== null) {
                            try {
                                this.showOverlay.showHtml(response);
                            } catch (err) {
                            }
                        }

                        try {
                            if ($type(languageSelect) === 'function') {
                                languageSelect();
                            }
                        } catch (err) {
                        }

                        try {
                            if (response.errors !== undefined) {
                                var errors = new Hash(response.errors);

                                target.getElements('input').each(function(el) {
                                    if (el.errors !== undefined) {
                                        el.errors = [];

                                        EFS.forms.formValidation.removeError(el);
                                    }
                                });

                                errors.each(function(errs, id) {
                                    var element = target.getElement('#' + id);
                                    var messages = new Hash(errs);

                                    element.errors = [];

                                    messages.each(function(message) {
                                        element.errors.push(message);
                                    });

                                    EFS.forms.formValidation.addError(element);
                                });
                            }
                        } catch (err) {
                        }

                        try {
                            callback(response);
                        } catch (err) {
                        }

                        if (response.callback) {
                            try {
                                switch (response.callback.action) {
                                    case this.actions.callbacks.reloadNotice:
                                        EFSHund.notices.starting();
                                    break;
                                    case this.actions.callbacks.reloadThemePacks:
                                        themePacks();
                                    break;
                                }
                            } catch (err) {
                            }
                        }
                    }.bind(this);

                    try {
                        if (response.preloadImage === undefined && $type(response.preloadImage) !== 'object') {
                            doActions(response);
                        } else {
                            new Asset.image(response.preloadImage.src, {
                                'alt': response.preloadImage.title,
                                'title': response.preloadImage.title,
                                onload: function() {
                                    this.inject($$('div#strip_title').getNext()[0], EFS.actions.where.top);

                                    doActions(response);
                                }
                            });
                        }
                    } catch (err) {
                    }
                }.bind(this),
                'onCancel': function() {
                    if (target !== undefined) {
                        mask.hide();
                        maskError.display();
                    }
                },
                'onException': function() {
                    if (target !== undefined) {
                        mask.hide();
                        maskError.display();
                    }
                },
                'onFailure': function() {
                    if (target !== undefined) {
                        mask.hide();
                        maskError.display();
                    }
                }
            };

            $extend(settings, options);

            new Request.JSON(settings).send();
        },
        mask: {
            error: {
                elements: {
                    container: null,
                    content: null
                },
                init: function(domto, i18n, callback) {
                    this.close();

                    try {
                        domto = domto === undefined ? document.body : domto;
                        $$(domto)[0].addClass('errorz');
                    } catch (err) {
                        domto = document.body;
                    }

                    new Element('span').inject(this.elements.container = new Element('div', {
                        'class': 'aerror'
                    }).hide(), EFS.actions.where.bottom);

                    this.elements.content = new Element('div').inject(new Element('div').inject(this.elements.container, EFS.actions.where.bottom), EFS.actions.where.bottom);

                    new Element('p', {
                        'html': '<strong>' + EFSHelpers.getTranslation(i18n) + '</strong>'
                    }).inject(this.elements.content, EFS.actions.where.bottom);

                    new Element('a', {
                        'class': 'button large nano',
                        'html': EFSHelpers.getTranslation('js.form.error_link'),
                        'events': {
                            'click': function(ev) {
                                ev = new Event(ev).stop();

                                this.hide();

                                domto.removeClass('errorz');

                                if (callback !== undefined) {
                                    callback();
                                }

                                return false;
                            }.bind(this)
                        }
                    }).inject(this.elements.content, EFS.actions.where.bottom);

                    $$(domto)[0].adopt(this.elements.container);

                    return this;
                },
                close: function() {
                    if (this.elements.container !== null) {
                        this.elements.container.dispose();
                    }
                },
                display: function() {
                    if (this.elements.container.isVisible() === false) {
                        this.elements.container.show();
                    }
                },
                hide: function() {
                    if (this.elements.container.isVisible() === true) {
                        this.elements.container.hide();
                    }
                }
            },
            show: {
                elements: {
                    container: null,
                    content: null
                },
                init: function(domto, i18n) {
                    this.close();

                    this.elements.content = new Element('div', {
                        'class': EFS.constants.classes.maskText,
                        'html': EFSHelpers.getTranslation(i18n)
                    }).inject(this.elements.container = new Element('div', {
                        'class': EFS.constants.classes.maskLoading
                    }), EFS.actions.where.bottom);

                    try {
                        domto = domto === undefined ? document.body : domto;
                    } catch (err) {
                        domto = document.body;
                    }

                    $$(domto)[0].adopt(this.elements.container);

                    return this;
                },
                close: function() {
                    if (this.elements.container !== null) {
                        this.elements.container.dispose();
                    }
                },
                display: function() {
                    if (this.elements.container.isVisible() === false) {
                        this.elements.container.show();
                    }
                },
                hide: function() {
                    if (this.elements.container.isVisible() === true) {
                        this.elements.container.hide();
                    }
                }
            }
        },
        elements: {
            stylishSelect: function(id) {
                var input = document.getElementById(id), div, textnode, option, active;

                option = input.getElementsByTagName('option');
                active = option[0].text;
                textnode = document.createTextNode(active);

                for (b = 0; b < option.length; b++) {
                    if (option[b].selected == true) {
                        textnode = document.createTextNode(option[b].text);
                    }
                }

                div = document.createElement('div');
                div.className = 'select ' + input.className;
                div.id = 'select' + input.name;
                div.appendChild(textnode);

                input.parentNode.insertBefore(div, input);

                if (!input.getAttribute('disabled')) {
                    input.onchange = function() {
                        option = this.getElementsByTagName('option');
                        for (d = 0; d < option.length; d++) {
                            if (option[d].selected == true) {
                                document.getElementById('select' + this.name).innerHTML = option[d].innerHTML;
                            }
                        }
                    };
                } else {
                    input.previousSibling.className = input.previousSibling.className += ' disabled';
                }
            },
            stylishRadio: function(id) {
                var input = document.getElementById(id), span, textnode, option, active;

                input.hide();

                span = document.createElement('span');
                span.className = 'radio';

                if (input.checked === true) {
                    span.className += ' rchecked';
                }

                input.parentNode.insertBefore(span, input);

                input.onchange = function() {
                    var inputs = document.getElementsByTagName('input');

                    for (var b = 0; b < inputs.length; b++) {
                        if (inputs[b].type === 'radio' && inputs[b].checked === true) {
                            inputs[b].previousSibling.className = 'radio rchecked';
                        } else if (inputs[b].type === 'radio') {
                            inputs[b].previousSibling.className = 'radio';
                        }
                    }
                };

                if (!input.getAttribute('disabled')) {
                    span.onmousedown = function() {
                        var element = this.nextSibling;

                        if (element.checked === true && element.type === 'radio') {
                            this.className = 'radio rchecked';
                        } else {
                            this.className = 'radio';
                        }
                    };

                    span.onmouseup = function() {
                        var element = this.nextSibling;

                        this.className = 'radio rchecked';

                        group = this.nextSibling.name;

                        var inputs = document.getElementsByTagName('input');

                        for (a = 0; a < inputs.length; a++) {
                            if (inputs[a].name == group && inputs[a] !== this.nextSibling) {
                                inputs[a].previousSibling.className = 'radio';
                            }
                        }

                        element.checked = true;
                    };
                } else {
                    span.className = span.className += ' disabled';
                }
            },
            highlight: function(options) {
                if ($type(options) === 'object') {
                    var settings = {
                        'index': 1,
                        'count': 3,
                        'colorFrom': '#fff',
                        'colorTo': '#fdfbe8',
                        'dom': null
                    };

                    $extend(settings, options);

                    if (settings.dom !== null) {
                        new Fx.Tween($$(settings.dom)[0], {
                            duration: 250,
                            wait: false
                        }).start('background-color', settings.colorFrom, settings.colorTo).chain(function(ev) {
                            this.start('background-color', settings.colorFrom).chain(function() {
                                if (settings.index < settings.count) {
                                    settings.index = settings.index + 1;

                                    EFS.elements.highlight(settings);
                                } else {
                                    $$(settings.dom)[0].removeProperty('style');
                                }
                            });
                        });
                    }
                } else if ($type(options) === 'array') {
                    options.each(function(option) {
                        EFS.elements.highlight(option);
                    }.bind(this));
                }
            },
            action: function(el, action, domTo) {
                // EFSHelpers.log('Executing command: ' + exe.Cmd + ' to ' + exe.DomTo);

                try {
                    if (action.command !== EFS.actions.commands.inserts) {
                        EFS.forms.init(el.getElements('form'));
                    }

                    switch (action.command) {
                        case EFS.actions.commands.inject:
                            el.inject(domTo, action.where);
                        break;
                        case EFS.actions.commands.append:
                            var children = el.getChildren();

                            switch (action.where) {
                                case EFS.actions.where.top:
                                    for (var i = children.length - 1; i >= 0; i--) {
                                        children[i].inject(domTo, action.where);
                                    }
                                break;
                                case EFS.actions.where.bottom:
                                    children.inject(domTo, action.where);
                                break;
                            }
                        break;
                        case EFS.actions.commands.replaces:
                            el.getChildren().replaces(domTo);
                        break;
                        case EFS.actions.commands.inserts:
                            domTo.setProperty('html', el.getProperty('html'));

                            EFS.forms.init(domTo.getElements('form'));
                        break;
                        case EFS.actions.commands.deleted:
                            domTo.dispose();
                        break;
                        default:
                            EFSHelpers.console.log('No command was given!', true);
                    }
                } catch (err) {
                }
            },
            create: function(options) {
                if ($type(options) === 'object') {
                    var settings = {
                        'dom': 'div',
                        'html': null,
                        'id': null,
                        'classes': null,
                        'command': EFS.actions.commands.inject,
                        'where': EFS.actions.where.bottom,
                        'domTo': 'body'
                    };

                    $extend(settings, options);

                    EFSHelpers.console.log('Creating element' + '<p>Dom: ' + settings.dom + '</p>' + '<p>domTo: ' + settings.domTo + '</p>' + '<p>Html: ' + settings.html + '</p>' + '<p>Id: ' + settings.id + '</p>' + '<p>Class: ' + settings.classes + '</p>', true);

                    var element = new Element(settings.dom, {
                        'html': settings.html !== null ? settings.html : null,
                        'id': settings.id !== null ? settings.id : null,
                        'class': settings.classes !== null ? settings.classes : null
                    });

                    var domTo = $type(settings.domTo) === 'string' ? $$(settings.domTo) : settings.domTo;

                    if ($type(domTo) === 'element') {
                        this.action(element, settings, domTo);
                    } else if ($type(domTo) === 'array') {
                        domTo.each(function(dom) {
                            element = new Element(settings.dom, {
                                'html': settings.html !== null ? settings.html : null,
                                'id': settings.id !== null ? settings.id : null,
                                'class': settings.classes !== null ? settings.classes : null
                            });

                            this.action(element, settings, dom);
                        }.bind(this));
                    }

                    return element;
                } else if ($type(options) === 'array') {
                    options.each(function(option) {
                        EFS.elements.create(option);
                    }.bind(this));
                }
            }
        },
        bubbles: function(element, options) {
            var settings = {
                'dom': 'span',
                'classes': 'bubble left',
                'command': this.actions.commands.inject,
                'where': this.actions.where.bottom
            };

            if ($type(options) === 'object') {
                $extend(settings, options);
            }

            $$(element).each(function(el) {
                try {
                    $extend(settings, {
                        'domTo': el
                    });

                    this.elements.create(settings);
                } catch (err) {
                }
            }.bind(this));
        },
        forms: {
            maxLength: 500,

            init: function(forms) {
                forms.each(function(form) {
                    if (this.formValidation.create(form) === false) {
                        if (form.hasClass(EFS.constants.classes.formAjax) === true) {
                            this.ajaxed(form);
                        } else if (form.hasClass(EFS.constants.classes.formNoSubmit) === false) {
                            this.submitted(form);
                        }
                    }

                    form.getElements('input.' + EFS.constants.classes.inputSelect).each(function(input) {
                        input.addEvent('click', function() {
                            this.select();
                        });
                    });

                    this.remaining(form);
                    this.expandable(form);

                    if (form.hasClass(EFS.constants.classes.formFocused) === true) {
                        this.focused(form.getElements('input[type="text"]'));
                        this.focused(form.getElements('input[type="password"]'));
                        this.focused(form.getElements('textarea'));
                    }

                    if (form.hasClass(EFS.constants.classes.styleSelect) === true) {
                        form.getElements('select').each(function(select, i) {
                            try {
                                EFS.elements.stylishSelect(select.id);
                            } catch (err) {
                            }
                        });

                        form.getElements('input[type="radio"]').each(function(radio, i) {
                            try {
                                EFS.elements.stylishRadio(radio.id);
                            } catch (err) {
                            }
                        });
                    }
                }.bind(this));
            },
            focused: function(el) {
                $$(el).each(function(input) {
                    var id = input.getProperty('id');
                    var label = input.getParent('form').getElement('label[for="' + id + '"]');

                    input.DefaultValue = label.getProperty('html').toString();

                    if (input.getProperty('value').trim() === '') {
                        input.setProperty('value', input.DefaultValue);
                    }

                    input.addEvents({
                        'focus': function() {
                            input.setProperty('value', input.getProperty('value').trim());

                            if (input.getProperty('value') === input.DefaultValue) {
                                input.setProperty('value', '');
                            }

//                            input.addClass('active');
                        },
                        'blur': function() {
                            input.setProperty('value', input.getProperty('value').trim());

                            if (input.getProperty('value').trim() === '') {
                                input.setProperty('value', input.DefaultValue);
                            }

//                            input.removeClass('active');
                        }
                    });
                });
            },
            submitted: function(form) {
                form.addEvent('submit', function(ev) {
                    EFS.mask.show.init(ev.target, 'js.form.loading');
                });
            },
            ajaxed: function(form) {
                form.addEvent('submit', function(ev) {
                    ev = new Event(ev).stop();

                    var target = ev.target;

                    if (target.hasClass(EFS.constants.classes.formNoSend) === false) {
                        EFS.ajax({
                            'url': target.getProperty('action'),
                            'data': target.toQueryString()
                        }, function(response) {
                            try {
                                target.getElements('textarea').setProperty('value', '');
                                EFS.forms.remaining(target, true);
                                EFS.forms.expandable(target);
                            } catch (err) {
                            }
                        }.bind(this), target);
                    }

                    return false;
                });
            },
            expandable: function(form) {
                if (form.hasClass(EFS.constants.classes.formExpandable) === true) {
                    form.getElements('textarea').each(function(textarea) {
                        setTimeout(function() {
                            new DynamicTextarea(textarea);
                        }, 1);
                    }.bind(this));
                }
            },
            remaining: function(form, reset) {
                if (form.hasClass(EFS.constants.classes.formRemaining) === true) {
                    form.getElements('textarea').each(function(textarea) {
                        var form = textarea.getParent('form');
                        var textRemaining = form.getElement('p b');

                        if(reset !== true) {
                            this.maxLength = parseInt(textRemaining.getProperty('html')) > 0 ? parseInt(textRemaining.getProperty('html')) : this.maxLength;
                        }

                        textRemaining.setProperty('html', (this.maxLength - textarea.value.length));

                        textarea.addEvents({
                            'keyup': function(ev) {
                                var target = ev.target;

                                if((this.maxLength - target.value.length) <= 50) {
                                    textRemaining.getParent().addClass('alert');
                                } else {
                                    textRemaining.getParent().removeClass('alert');
                                }

                                if (this.maxLength < target.value.length) {
                                    target.value = target.value.substr(0, this.maxLength);
                                }

                                textRemaining.setProperty('html', (this.maxLength - target.value.length));
                            }.bind(this),
                            'keydown': function(ev) {
                                var target = ev.target;

                                if (this.maxLength <= target.value.length) {
                                    if (ev.key == 'up' || ev.key == 'down' || ev.key == 'left' || ev.key == 'right' || ev.key == 'backspace' || ev.key == 'delete') {
                                    } else {
                                        target.value = target.value.substr(0, this.maxLength);

                                        ev.stop();
                                    }
                                }
                            }.bind(this)
                        });
                    }.bind(this));
                }
            },
            formValidation: {
                alerts: {
                    'required': 'js.form.helpme.description',
                    'username': 'js.form.register.username',
                    'usernameExist': 'js.form.register.usernameExists',
                    'email': 'js.form.register.email',
                    'emailExist': 'js.form.register.emailExists',
                    'email2': 'js.form.register.email2',
                    'password': 'js.form.register.password',
                    'number': 'js.form.register.number'
                },

                create: function(form) {
                    if (form !== null && form.getElements("*[class*=validate]").length > 0) {
                        this.form = form;
                        this.form.isValid = true;
                        this.alreadyIndicated = false;
                        this.firstError = false;
                        this.validations = [];
                        this.regExp = [];

                        var regExp = new Hash(EFS.regExp);

                        regExp.each(function(el, key) {
                            this.regExp.push(key);
                        }.bind(this));

                        this.form.getElements("*[class*=validate]").each(function(el) {
                            if (el.get('tag') === 'input' || el.get('tag') === 'textarea') {
                                this.register(el);
                            }
                        }.bind(this));

                        this.form.addEvent('submit', this.onSubmit.bind(this));

                        return true;
                    }

                    return false;
                },
                onSubmit: function(ev) {
                    ev = new Event(ev).stop();

                    this.reInitialize();

                    this.validations.each(function(el) {
                        if (this.manageErrors(el) === false) {
                            this.form.isValid = false;
                        }
                    }.bind(this));

                    if (this.form.isValid && this.form.hasClass(EFS.constants.classes.formNoSend) === false) {
                        EFS.ajax({
                            'url': this.form.getProperty('action'),
                            'data': this.form.toQueryString()
                        }, function(response) {
                            if (response.status === true && response.form !== undefined) {
                                this.elements.overlay.show();
                                this.elements.container.show();
                                this.elements.div.setProperty('html', response.form);

                                this.init();
                            }
                        }.bind(this), ev.target);
                    } else if (this.elementToRemove && this.elementToRemove !== this.firstError) {
                        this.removeError(this.elementToRemove);
                    }

                    return false;
                },
                reInitialize: function() {
                    this.validations.each(function(el) {
                        if (el.element !== undefined) {
                            el.errors = [];
                            el.isOK = true;
                        }
                    }.bind(this));

                    this.firstError = false;
                    this.elementToRemove = this.alreadyIndicated;
                    this.alreadyIndicated = false;
                    this.form.isValid = true;
                },
                register: function(el) {
                    el.validation = [];
                    el.getProperty('class').split(' ').each(function(classX) {
                        if (classX.match(EFS.regExp.validate)) {
                            var validators = eval(classX.match(EFS.regExp.validate)[1]);

                            for (var i = 0; i < validators.length; i = i + 1) {
                                el.validation.push(validators[i]);

                                if (validators[i].match(/^confirm\[/)) {
                                    var field = eval(validators[i].match(/^.+(\[.+\])$/)[1].replace(/([A-Z0-9\._-]+)/i, "'$1'"));

                                    if (this.form[field].validation.contains('required') === true) {
                                        el.Validation.push('required');
                                    }

                                }
                            }

                            this.validations.push(el);
                            this.addListener(el);
                        }
                    }.bind(this));
                },
                addListener: function(el) {
                    el.errors = [];

                    el.addEvent('blur', function() {
                        (function() {
                            this.manageErrors(el);
                        }.bind(this)).delay(100);
                    }.bind(this));

                    el.validation.each(function(rule) {
                        if (rule.toLowerCase() === 'number') {
                            el.addEvent('keypress', function(ev) {
                                var charCode = ev.event.charCode;
                                var keyCode = ev.event.keyCode;

                                // charCode, if ASCII is pressed (must be greater then 0)
                                // keyCode, if 'operation' key is pressed (must be greater then zero)
                                if (charCode > 0 && keyCode === 0) {
                                    // only numbers and . and ,
                                    if ((48 <= charCode && charCode <= 57) || charCode === 44 || charCode === 46) {
                                        return true;
                                    } else {
                                        return false;
                                    }
                                }
                            });
                        }
                    });
                },
                validateRegExp: function(el, ruleMethod, ruleArgs) {
                    var msg = EFSHelpers.getTranslation(this.alerts[ruleMethod]);

                    if (EFS.regExp[ruleMethod].test(el.value) === false) {
                        el.errors.push(msg);

                        return false;
                    }

                    return true;
                },
                validate: function(el) {
                    el.errors = [];
                    el.isOk = true;

                    if (el.getProperty('disabled')) {
                        return true;
                    }

                    el.value = el.value.trim();

                    el.validation.each(function(rule) {
                        var ruleArgs = [];
                        var ruleMethod = rule;

                        if (rule.match(/^.+\[/)) {
                            ruleMethod = rule.split('[')[0];
                            ruleArgs = eval(rule.match(/^.+(\[.+\])$/)[1].replace(/([A-Z0-9\._-]+)/i, "'$1'"));
                        }

                        if (this.regExp.contains(ruleMethod)) {
                            el.isOk = this.validateRegExp(el, ruleMethod, ruleArgs);
                        }

                        if (rule.match(/%[A-Z0-9\._-]+$/i) || (el.isOk && rule.match(/~[A-Z0-9\._-]+$/i))) {
                            el.isOk = eval(rule.slice(1) + '(el)');
                        }
                    }.bind(this));

                    return el.isOk;
                },
                removeError: function(obj, method) {
                    obj.removeClass('error');

                    if (obj.element === false) return;

                    this.alreadyIndicated = false;

                    obj.errors = [];
                    obj.isOK = true;

                    if (obj.element !== undefined) {
                        obj.element.hide();
                        // obj.element = false;
                    }
                },
                addError: function(obj) {
                    if (obj.element === undefined) {
                        obj.element = new Element('ul', {
                            'class': 'errors'
                        }).hide().inject(obj, EFS.actions.where.after);
                    }

                    if (obj.element && obj.element !== undefined) {
                        obj.element.empty();

                        obj.errors.each(function(error) {
                            EFS.elements.create({
                                'dom': 'li',
                                'html': error,
                                'command': EFS.actions.commands.inject,
                                'where': EFS.actions.where.bottom,
                                'domTo': obj.element
                            });
                        });

                        obj.element.show();
                    }

                    obj.addClass('error');
                    obj.element = obj.element || true;
                },
                manageErrors: function(el) {
                    var isValid = this.validate(el);

                    if ((isValid === false && el.validation.flatten()[0].contains('confirm[') === true) || (isValid === false && el.validation.contains('required') === true) || (el.validation.contains('required') === false && isValid === false)) {
                        if (this.alreadyIndicated === false || el.name === this.alreadyIndicated.name) {
                            if (this.firstError === false) {
                                this.firstError = el;
                            }

                            this.alreadyIndicated = el;

                            this.addError(el);

                            return false;
                        }
                    } else if ((isValid === true || (el.validation.contains('required') === false && el.value === false))) {
                        this.removeError(el);

                        return true;
                    }

                    return true;
                }
            }
        },
        showWindow: {
            elements: [],

            close: function(target) {
                target = target.getParent('.selected');

                this.elements.each(function(popup) {
                    if (target !== popup || target === null) {
                        popup.removeClass('selected');
                    }
                });
            },
            toggle: function(el) {
                if (el.hasClass('selected') === true) {
                    el.removeClass('selected');
                } else {
                    el.addClass('selected');
                }
            },
            init: function() {
                $$('a.' + EFS.constants.classes.showWindow).each(function(popup) {
                    try {
                        var div = popup.getParent();
                        this.elements.push(div);

                        popup.addEvent('click', function(ev) {
                            try {
                                ev = new Event(ev).stop();

                                this.close($$(ev.target)[0]);
                                this.toggle(div);
                                $$('input.autofocus')[0].focus();

                                return false;
                            } catch (err) {
                            }
                        }.bind(this));
                    } catch (err) {
                    }
                }.bind(this));
            }
        },
        showMore: {
            elements: [],

            close: function(target) {
                target = target.getParent('.selected');

                this.elements.each(function(popup) {
                    if (target !== popup || target === null) {
                        popup.removeClass('selected');
                    }
                });
            },
            toggle: function(el) {
                if (el.hasClass('selected') === true) {
                    el.removeClass('selected');
                } else {
                    el.addClass('selected');
                }
            },
            init: function(el) {
                $$(el).each(function(popup) {
                    try {
                        var div = popup.getParent();
                        this.elements.push(div);

                        popup.addEvent('click', function(ev) {
                            try {
                                ev = new Event(ev).stop();

                                this.close($$(ev.target)[0]);
                                this.toggle(div);

                                return false;
                            } catch (err) {
                            }
                        }.bind(this));
                    } catch (err) {
                    }
                }.bind(this));
            }
        },
        showOverlay: {
            settings: {
                close: true
            },
            elements: {
                overlay: null,
                container: null,
                div: null
            },

            create: function(domto) {
                this.close();

                this.elements.overlay = new Element('div', {
                    'id': EFS.constants.ids.overlay
                }).hide();

                this.elements.div = new Element('div').inject(this.elements.container = new Element('div', {
                    'id': EFS.constants.ids.container
                }).hide(), EFS.actions.where.bottom);

                try {
                    domto = domto === undefined ? document.body : domto;
                } catch (err) {
                    domto = document.body;
                }

                $$(domto)[0].adopt(this.elements.overlay, this.elements.container);
            },
            getVisible: function() {
                try {
                    return this.elements.overlay !== null && this.elements.overlay.isVisible() && this.elements.container !== null && this.elements.container.isVisible();
                } catch (err) {
                    return false;
                }
            },
            close: function() {
                if (this.settings.close === true) {
                    if (this.elements.overlay !== null) {
                        this.elements.overlay.dispose();
                    }

                    if (this.elements.container !== null) {
                        this.elements.container.dispose();
                    }
                }
            },
            onClick: function(ev) {
                ev = new Event(ev).stop();

                EFS.showOverlay.settings.close = true;

                this.close();

                return false;
            },
            onSubmit: function(ev) {
                ev = new Event(ev).stop();

                var target = ev.target;

                EFS.ajax({
                    'url': target.getProperty('action'),
                    'method': target !== undefined ? (target.getProperty('method') !== null ? target.getProperty('method') : 'GET') : 'GET',
                    'data': target.toQueryString()
                }, function(response) {
                }.bind(this), target);

                return false;
            },
            init: function(response) {
                if (this.elements.container.getElements('a.' + EFS.constants.classes.closeOverlay).length > 0) {
                    this.elements.container.getElements('a.' + EFS.constants.classes.closeOverlay).addEvent('click', this.onClick.bind(this));
                }

                if (this.elements.container.getElement('form') !== null) {
                    if (EFS.forms.formValidation.create(this.elements.container.getElement('form')) === false) {
                        this.elements.container.getElement('form').addEvent('submit', this.onSubmit.bind(this));
                    }

                    if (this.elements.container.getElement('form#help select') !== null) {
                        var select = this.elements.container.getElement('form#help select');
                        var label = this.elements.container.getElement('form#help label[for="title"]');
                        var input = this.elements.container.getElement('form#help input[name="title"]');

                        if (select.getSelected()[0].getProperty('value') !== 0) {
                            label.hide();
                            input.hide();
                        }

                        select.addEvent('change', function(ev) {
                            if (ev.target.value == 0) {
                                label.show();
                                input.show();
                            } else {
                                label.hide();
                                input.hide();
                            }
                        });
                    }

                    if (this.elements.container.getElements('form.' + EFS.constants.classes.styleSelect + ' select').length > 0) {
                        this.elements.container.getElements('form.' + EFS.constants.classes.styleSelect + ' select').each(function(select, i) {
                            try {
                                EFS.elements.stylishSelect(select.id);
                            }
                            catch (err) {
                            }
                        });
                    }

                    if (this.elements.container.getElements('form.' + EFS.constants.classes.styleSelect + ' input[type="radio"]').length > 0) {
                        this.elements.container.getElements('form.' + EFS.constants.classes.styleSelect + ' input[type="radio"]').each(function(radio, i) {
                            try {
                                EFS.elements.stylishRadio(radio.id);
                            }
                            catch (err) {
                            }
                        });
                    }

                    try {
                        if (this.elements.container.getElement('form input#tags') !== null) {
                            EFS.autoComplete.init(this.elements.container.getElement('form input#tags'));
                        }
                    }
                    catch (err) {
                    }

                    try {
                        if (this.elements.container.getElement('form select#repeat') !== null) {
                            var repeat_day_label = this.elements.container.getElement('form #repeat_day-label');
                            var repeat_day_element = this.elements.container.getElement('form #repeat_day-element');
                            var repeat_month_element = this.elements.container.getElement('form #repeat_month-element');
                            var repeat_year_element = this.elements.container.getElement('form #repeat_year-element');

                            repeat_day_label.hide();
                            repeat_day_element.hide();
                            repeat_month_element.hide();
                            repeat_year_element.hide();

                            this.elements.container.getElement('form select#repeat').addEvent('change', function(ev) {
                                repeat_day_label.hide();
                                repeat_day_element.hide();
                                repeat_month_element.hide();
                                repeat_year_element.hide();

                                try {
                                    if (parseInt(ev.target.value) !== -1 && ev.target.value.length < 2) {
                                        repeat_day_label.show();
                                        repeat_day_element.show();
                                        repeat_month_element.show();
                                        repeat_year_element.show();
                                    }
                                }
                                catch (err) {
                                }
                            });
                        }
                    }
                    catch (err) {
                    }

                    try {
                        if (this.elements.container.getElement('form select#currency') !== null && this.elements.container.getElement('form input#exchange_rates') !== null) {
                            var currency = this.elements.container.getElement('form select#currency');
                            // Find exchange rate input
                            var exchange_rate = this.elements.container.getElement('form input#exchange_rate');
                            // Find exchange rate hidden input
                            var exchange_rates = this.elements.container.getElement('form input#exchange_rates').value.split(';');

                            // Find label to hide
                            var exchange_rate_label = this.elements.container.getElement('form #exchange_rate-label');
                            // Which currency is default?
                            var default_currency = $('default_currency').value;
                            var selected_index = this.elements.container.getElement('form select#currency').selectedIndex;

                            // Find custom currency element
                            var custom_currency = this.elements.container.getElement('form #custom_currency');
                            var custom_currency_dd = this.elements.container.getElement('form #currency-element + dd');
                            // Find amount element to style
                            var amount_element = this.elements.container.getElement('form #amount-element .input');
                            // Find select for currency
                            var currency_element = this.elements.container.getElement('form #currency-element');
                            // Find button for custom currency to close
                            var closeCustomCurrency = this.elements.container.getElement('form .closeCustomCurrency');

                            var conversion_text = new Element('strong', {
                                'html': '1 ' + $('default_currency').getProperty('value') + ' = '
                            });

                            var currency_text = new Element('strong', {
                                'html': ' ' + $$(currency).getSelected()[0].getProperty('value')
                            });

                            $$(custom_currency).addEvent('keyup', function() {
                                $$(currency_text)[0].setProperty('html', $$(this).getProperty('value'));
                            });

                            $$(conversion_text).inject($$(exchange_rate)[0], 'before');
                            $$(currency_text).inject($$(exchange_rate)[0], 'after');

                            if(default_currency === currency.value) {
                                $$(exchange_rate_label).hide();
                                $$(exchange_rate_label).getNext().hide();
                            } else {
                                $$(exchange_rate_label).show();
                                $$(exchange_rate_label).getNext().show();
                            }
                            $$(custom_currency).hide();
                            $$(custom_currency_dd).hide();
                            $$(closeCustomCurrency).hide();
                            $$(amount_element).removeClass('custom');

                            // Event for closing all custom inputs
                            $$(closeCustomCurrency).addEvent('click', function(ev) {
                                ev = new Event(ev).stop();

                                $$(exchange_rate_label).hide();
                                $$(exchange_rate_label).getNext().hide();
                                $$(custom_currency).hide();
                                $$(custom_currency_dd).hide();
                                $$(closeCustomCurrency).hide();
                                $$(amount_element).removeClass('custom');
                                $$(currency_element).show();
                                currency.selectedIndex = selected_index;
                                $$(currency).getPrevious().setProperty('html', $$(currency).getSelected()[0].getProperty('value'));

                                return false;
                            });

                            $$(currency).addEvent('change', function(ev) {
                                $$(exchange_rate_label).hide();
                                $$(exchange_rate_label).getNext().hide();
                                $$(custom_currency).hide();
                                $$(custom_currency_dd).hide();
                                $$(closeCustomCurrency).hide();
                                $$(amount_element).removeClass('custom');
                                $$(currency_element).show();

                                try {
                                    if (this.value !== default_currency) {
                                        if (this.selectedIndex !== currency.length - 1) {
                                            $$(currency_text)[0].setProperty('html', $$(this).getSelected()[0].getProperty('value'));
                                        } else {
                                            $$(currency_text)[0].setProperty('html', $$(custom_currency)[0].getProperty('value'));
                                            $$(custom_currency).show();
                                            $$(custom_currency_dd).show();
                                            $$(closeCustomCurrency).show();
                                            $$(amount_element).addClass('custom');
                                            $$(currency_element).hide();
                                        }

                                        $$(exchange_rate_label).show();
                                        $$(exchange_rate_label).getNext().show();
                                    }
                                }
                                catch (err) {
                                }

                                for (var i = 0; i <= exchange_rates.length - 1; i++) {
                                    var current = exchange_rates[i].split(':');

                                    if (current[0].toLowerCase() === this.value.toLowerCase()) {
                                        try {
                                            exchange_rate.value = current[1];
                                        }
                                        catch (err) {
                                        }

                                        break;
                                    }
                                }
                            });
                        }
                    }
                    catch (err) {
                    }

                    try {
                        if (this.elements.container.getElements('form dd#tags_list div ul li').length > 0 && this.elements.container.getElement('form input#tags') !== null) {
                            // get width of ul tags
                            var tags_list_width = this.elements.container.getElements('form dd#tags_list div ul').getWidth();
                            // get list of tags
                            var tags_list_reorder = this.elements.container.getElements('form dd#tags_list div ul li');
                            // create temporary width
                            var reorder_width = 0;
                            var reorder_row = 1;

                            // create temporary elements
                            var temp_div = new Element('div'), temp_ul = new Element('ul');
                            temp_ul.inject(temp_div);

                            tags_list_reorder.each(function(tag_list_reorder) {
                                var tag_list_reorder_width = tag_list_reorder.getWidth() + parseInt(tag_list_reorder.getStyle('margin-right'));

                                reorder_width = reorder_width + tag_list_reorder_width;

                                if (reorder_width > tags_list_width && reorder_row === 1) {
                                    reorder_width = 0 + tag_list_reorder_width;
                                    reorder_row = 2;
                                } else if (reorder_width > tags_list_width && reorder_row === 2) {
                                    temp_ul = new Element('ul');
                                    temp_ul.inject(temp_div, 'bottom');

                                    reorder_width = 0 + tag_list_reorder_width;
                                    reorder_row = 1;

                                    new Element('li', {
                                        'html': 'o'
                                    }).inject($$('form dd#tags_list ul.bullets')[0], 'bottom');
                                }

                                tag_list_reorder.inject(temp_ul, 'bottom');
                            });

                            $$('form dd#tags_list div').setProperty('html', temp_div.getProperty('html'));

                            // get elements div
                            var list = $$('form dd#tags_list div');
                            // get children of element
                            var listItems = list[0].getChildren('ul');

                            // get element bullets
                            var bullets = $$('form dd#tags_list ul.bullets');
                            // get children of element
                            var bulletsPaging = bullets[0].getChildren('li');
                            // count all elements
                            var bulletsCount = bulletsPaging.length;

                            // calculate width of all list items
                            var widthListItems = listItems[0].getWidth();
                            // calculate width with 1 element in it
                            var widthList = widthListItems;

                            // set width of ul.list
                            list.setStyle('width', listItems.length * widthListItems);

                            // recursion to get index
                            var itemSelectedForPaging = function(index, item) {
                                // check if previous element is not null
                                if (item.getPrevious() !== null) {
                                    // increase index by 1
                                    index = index + 1;
                                    // recursive call
                                    return itemSelectedForPaging(index, item.getPrevious());
                                }

                                // return index
                                return index;
                            };

                            // add event
                            bulletsPaging.addEvent('click', function(ev) {
                                // remove class from elements
                                bulletsPaging.removeClass('selected');
                                // add class to clicked element
                                this.addClass('selected');

                                // calcute how much must we move element to left, call recursive to get which element is clicked
                                var left = (-1) * (widthList * (itemSelectedForPaging(1, this) - 1));

                                // create animation with attributes
                                new Fx.Tween(list[0], {
                                    duration: 250,
                                    wait: false
                                }).start('left', list.getProperty('left'), left);
                            });

                            /*
                             * Logic for adding tags
                             * */
                            var tags = this.elements.container.getElement('form input#tags');
                            var tags_list = this.elements.container.getElements('form dd#tags_list div ul li');

                            var values = tags.getProperty('value').clean();
                            var value = values.split(',');

                            for (var x = 0; x <= tags_list.length - 1; x++) {
                                var tag = tags_list[x];
                                var text = tag.getProperty('text').clean();

                                for (var y = 0; y <= value.length - 1; y++) {
                                    var val = value[y].clean();

                                    if (val.toLowerCase() === text.toLowerCase()) {
                                        tag.addClass('selected');

                                        break;
                                    }
                                }
                            }

                            tags_list.addEvent('click', function(ev) {
                                ev = new Event(ev).stop();
                                var target = ev.target, bRemove = target.hasClass('selected'), text = target.getProperty('text'), values = tags.getProperty('value').split(','), i = 0, val = '';

                                if (bRemove === true) {
                                    target.removeClass('selected');
                                } else {
                                    target.addClass('selected');
                                }

                                for (i = 0; i <= values.length - 1; i++) {
                                    var value = values[i].clean();

                                    if (bRemove === true) {
                                        if (value.toLowerCase() !== text.toLowerCase() && value !== '') {
                                            val = val + value + ', ';
                                        }
                                    } else {
                                        if (value.toLowerCase() === text.toLowerCase()) {
                                            break;
                                        } else {
                                            if (value === '') {
                                                value = text;
                                            } else if (value !== '' && i === values.length - 1) {
                                                value = value + ', ' + text;
                                            }

                                            val = val + value + ', ';
                                        }
                                    }
                                }

                                tags.setProperty('value', val).setCaretPosition('end');

                                return false;
                            }.bind(this));
                        }
                    }
                    catch (err) {
                    }

                    EFS.showMore.init(this.elements.container.getElements('a.' + EFS.constants.classes.showMore));
                }

                if (response.domTo !== undefined && response.scrollTo != undefined)
                {
                    try
                    {
                        var neededHeight    = this.elements.div.getSize().y;
                        var availableHeight = $$('#statz')[0].getCoordinates().height < 700 ? 700 : $$('#statz')[0].getCoordinates().height;
                        var offset = $$(response.scrollTo)[0].getCoordinates().top - $$(response.domTo)[0].getCoordinates().top;
                        if (availableHeight - neededHeight - offset < 0)
                        {
                            // move edit screen up
                            $$(this.elements.container)[0].setPosition({
                                'y': availableHeight - neededHeight - 13
                            });
                        }
                        else
                        {
                            // aling to line
                            $$(this.elements.container)[0].setPosition({
                                'y': offset - 13
                            });

//                            new Fx.Scroll(window).start(0, $$(this.elements.div)[0].getCoordinates().top - 36);
                        }
                    }
                    catch (err) {}
                }
            },
            getVisible: function() {
                try {
                    return this.elements.overlay !== null && this.elements.overlay.isVisible() && this.elements.container !== null && this.elements.container.isVisible();
                } catch (err) {
                    return false;
                }
            },
            show: function(url) {
                if (url !== undefined) {
                    EFS.ajax({
                        'url': url
                    }, function(response) {
                        if (response.status === true && response.form !== undefined) {
                            this.create(response.domTo !== undefined ? response.domTo : undefined);

                            this.elements.overlay.show();
                            this.elements.container.show();
                            this.elements.div.setProperty('html', response.form);

                            this.init(response);
                        }
                    }.bind(this));
                }
            },
            showHtml: function(response) {
                if (response.overlay !== undefined) {
                    this.create(response.domTo !== undefined ? response.domTo : undefined);

                    this.elements.overlay.show();
                    this.elements.container.show();
                    this.elements.div.setProperty('html', response.overlay);

                    this.init(response);
                }
            }
        },
        autoComplete: {
            settings: {
                showMax: 6,
                currentSelection: null
            },
            elements: {
                input: null,
                suggestList: null
            },
            decodeXml: function(str) {
                var escaped_one_to_xml_special_map = {
                    '&amp;': '&',
                    '&quot;': '"',
                    '&lt;': '<',
                    '&gt;': '>'
                };

                return str.replace(/(&quot;|&lt;|&gt;|&amp;)/g, function(s, item) {
                    return escaped_one_to_xml_special_map[item];
                });
            },
            create: function() {
                this.elements.suggestList = new Element('ul', {
                    'class': 'autoSuggest',
                    'events': {
                        'mouseover': function(ev) {
                            var target = ev.target;

                            if (target.nodeName.toLowerCase() === 'li' && target.hasClass('bottom') === false) {
                                this.elements.suggestList.getElements('li.selected').removeProperty('class');

                                target.addClass('selected');
                            }
                        }.bind(this),
                        'mouseout': function() {
                            this.elements.suggestList.getElements('li.selected').removeProperty('class');
                        }.bind(this),
                        'click': function(ev) {
                            var target = ev.target;

                            if (target.nodeName.toLowerCase() === 'li' && target.hasClass('bottom') === false) {
                                var text = '';

                                var input = this.elements.input;
                                var value = input.value;
                                var caretPosition = input.getCaretPosition();
                                var remainingText = input.getTextInRange(caretPosition, value.length);
                                var startText = input.getTextInRange(0, caretPosition);

                                if (startText.indexOf(',') > -1) {
                                    for (var i = caretPosition; i >= 0; i--) {
                                        if (startText[i] === ',') {
                                            text = startText.substr(0, i);

                                            break;
                                        }
                                    }
                                }

                                if (text !== '') {
                                    text = text + ', ';
                                }

                                input.value = text + target.textContent;

                                if (text !== '') {
                                    input.setCaretPosition('end');
                                }

                                input.value = input.value + ', ';

                                this.searching = false;
                                this.elements.suggestList.hide();
                                this.reset();
                                this.checkList();
                            }
                        }.bind(this)
                    }
                }).hide().inject(this.elements.input.getParent(), 'bottom');

                this.reset();
            },
            reset: function() {
                this.settings.currentSelection = null;

                this.elements.suggestList.getChildren().each(function(item, index) {
                    if (item.hasClass('bottom') === false) {
                        item.dispose();
                    }
                });
            },
            markupSuggestion: function(tag, value) {
                var marked = '<strong>' + value + '</strong>';
                var et_regex = new RegExp('(' + value + ')', 'i');

                return tag.replace(et_regex, '<strong>$1</strong>');
            },
            setSelection: function(el) {
                this.elements.suggestList.getElements('li.selected').removeProperty('class');

                this.settings.currentSelection = el;

                if (el !== null) {
                    el.addClass('selected');
                }
            },
            search: function(value) {
                this.reset();
                var val = '';
                var found = 0;

                for (var i = 0; i <= this.tags.length - 1; i++) {
                    if (found < this.settings.showMax && this.tags[i].tag.toLowerCase().indexOf(value.toLowerCase()) === 0 && this.tags[i].show === true && this.isReturnTagUsed(this.decodeXml(this.tags[i].tag)) === false) {
                        if (val === '') {
                            val = this.decodeXml(this.tags[i].tag).slice(value.length);
                        }

                        var li = new Element('li', {
                            html: this.markupSuggestion(this.tags[i].tag, value)
                        }).inject(this.elements.suggestList, EFS.actions.where.bottom);

                        this.elements.suggestList.show();
                        found = found + 1;
                    }
                }

                if (found === 0) {
                    this.elements.suggestList.hide();
                }

                return val;
            },
            isReturnTagUsed: function(search) {
                var tags = $$('form input#tags')[0];

                var values = tags.getProperty('value').clean();
                var value = values.split(',');

                for (var y = 0; y <= value.length - 1; y++) {
                    var val = value[y].clean();

                    if (val.toLowerCase() === search.toLowerCase()) {
                        return true;
                    }
                }

                return false;
            },
            checkList: function() {
                var tags = $$('form input#tags')[0];
                var tags_list = $$('form dd#tags_list div ul li');

                tags_list.removeClass('selected');

                var values = tags.getProperty('value').clean();
                var value = values.split(',');

                for (var x = 0; x <= tags_list.length - 1; x++) {
                    var tag = tags_list[x];
                    var text = tag.getProperty('text').clean();

                    for (var y = 0; y <= value.length - 1; y++) {
                        var val = value[y].clean();

                        if (val.toLowerCase() === text.toLowerCase()) {
                            tag.addClass('selected');

                            break;
                        }
                    }
                }
            },
            init: function(el) {
                if ($$(el).length === 1) {
                    EFS.showOverlay.settings.close = false;

                    EFS.ajax({
                        'url': EfsConfig.tags.list
                    }, function(response) {
                        EFS.showOverlay.settings.close = true;

                        if (response.status === true && response.tags !== undefined) {
                            this.elements.input = $$(el)[0];
                            this.searching = false;
                            this.tags = [];

                            $each(response.tags, function(tag, t) {
                                this.tags.push({
                                    'show': true,
                                    'tag': tag
                                });
                            }.bind(this));

                            this.create();

                            this.elements.input.addEvents({
                                'keyup': function(ev) {
                                    var keyCode = ev.event.keyCode;
                                    var target = ev.target;
                                    var value = target.value;

                                    var caretPosition = target.getCaretPosition();
                                    var remainingText = target.getTextInRange(caretPosition, value.length);

                                    if (keyCode !== 8 && keyCode !== 46 && keyCode !== 38 && keyCode !== 40 && remainingText.indexOf(',') === -1) {
                                        var startText = target.getTextInRange(0, caretPosition);

                                        if (startText.indexOf(',') > -1) {
                                            for (var i = caretPosition; i >= 0; i--) {
                                                if (startText[i] === ',') {
                                                    value = target.getTextInRange(i + 1, value.length).clean();

                                                    break;
                                                }
                                            }
                                        }

                                        if (value !== '') {
                                            var suggest = this.search(value);

                                            if (suggest !== '') {
                                                target.insertAtCursor(suggest, true);

                                                this.searching = true;
                                            }
                                        } else {
                                            var value = target.value.clean().split(',');
                                            target.value = '';

                                            for (var y = 0; y <= value.length - 1; y++) {
                                                var val = value[y].clean();

                                                if (val !== '') {
                                                    var bFound = false;

                                                    for (var x = y + 1; x <= value.length - 1; x++) {
                                                        var temp = value[x].clean();

                                                        if (temp.toLowerCase() === val.toLowerCase()) {
                                                            bFound = true;

                                                            break;
                                                        }
                                                    }

                                                    if (bFound === false) {
                                                        target.value = target.value + val + ', ';
                                                    }
                                                }
                                            }

                                            this.checkList();
                                        }
                                    } else if (keyCode !== 38 && keyCode !== 40) {
                                        this.checkList();
                                        this.elements.suggestList.hide();
                                    }
                                }.bind(this),
                                'keydown': function(ev) {
                                    var keyCode = ev.event.keyCode;

                                    if ((keyCode === 13 || keyCode === 9 || keyCode === 188 || keyCode === 38 || keyCode === 40) && this.searching === true) {
                                        ev = new Event(ev).stop();

                                        var target = ev.target;

                                        if (keyCode !== 38 && keyCode !== 40) {
                                            var text = '';

                                            if (this.settings.currentSelection === null) {
                                                text = target.getSelectedText().clean();
                                            } else {
                                                var value = target.value;
                                                var caretPosition = target.getCaretPosition();
                                                var remainingText = target.getTextInRange(caretPosition, value.length);
                                                var startText = target.getTextInRange(0, caretPosition);

                                                if (startText.indexOf(',') > -1) {
                                                    for (var i = caretPosition; i >= 0; i--) {
                                                        if (startText[i] === ',') {
                                                            text = startText.substr(0, i);

                                                            break;
                                                        }
                                                    }
                                                }

                                                if (text !== '') {
                                                    text = text + ', ';
                                                }

                                                target.value = text + this.settings.currentSelection.textContent;
                                            }

                                            if (text !== '') {
                                                target.setCaretPosition('end');
                                            }

                                            target.value = target.value + ', ';

                                            this.checkList();
                                            this.searching = false;
                                            this.elements.suggestList.hide();
                                            this.reset();
                                        } else if (this.elements.suggestList.isDisplayed() === true) {
                                            var el = null;

                                            if (keyCode === 40) {
                                                if (this.settings.currentSelection === null) {
                                                    el = this.elements.suggestList.getFirst();
                                                } else if (this.settings.currentSelection.getNext() == null || this.settings.currentSelection.getNext().hasClass('bottom')) {
                                                    el = this.elements.suggestList.getFirst();
                                                } else {
                                                    el = this.settings.currentSelection.getNext();
                                                }
                                            } else if (keyCode === 38) {
                                                if (this.settings.currentSelection === null) {
                                                    el = this.elements.suggestList.getLast().getPrevious();
                                                } else if (this.settings.currentSelection.getPrevious() == null) {
                                                    el = this.elements.suggestList.getLast().getPrevious();
                                                } else {
                                                    el = this.settings.currentSelection.getPrevious();
                                                }
                                            }

                                            try {
                                                target.insertAtCursor(el.childNodes[1].textContent, true);
                                            } catch (err) {
                                            }

                                            this.setSelection(el);
                                        }

                                        return false;
                                    }
                                }.bind(this)
                            });
                        }
                    }.bind(this));
                }
            }
        },
        domInit: function() {
            if (this.isDomReady === false) {
                // DOM has loaded for first time and dont reload another functionality then this !
                this.isDomReady = true;

                $(document).addEvents({
                    'click': function(ev) {
                        try {
                            var target = ev.target;
                            var nodeName = target.nodeName.toLowerCase();

                            if (nodeName === 'a' && ($(target).hasClass(this.constants.classes.showOverlay) === true || $(target).hasClass(this.constants.classes.ajax) === true || target.rel.test('external'))) {
                                ev = new Event(ev).stop();

                                if (target.rel.test('external') === true) {
                                    window.open(ev.target.href, '_blank');
                                } else if ($(target).hasClass(this.constants.classes.showOverlay) === true) {
                                    this.showOverlay.show(target.href);
                                } else if ($(target).hasClass(this.constants.classes.ajax) === true) {
                                    var lajax = undefined;

                                    $(target).getProperty('class').split(' ').each(function(classX) {
                                        if (classX.match(EFS.regExp.lajax)) {
                                            var validators = eval(classX.match(EFS.regExp.lajax)[1]);

                                            if ($$(validators).length === 1) {
                                                lajax = $$(validators)[0];
                                            }
                                        }
                                    }.bind(this));

                                    EFS.ajax({
                                        'url': $(target).getProperty('href')
                                    }, function(response) {
                                    }.bind(this), lajax);
                                }

                                return false;
                            } else {
                                this.showWindow.close($$(target)[0]);
                                /*
                                 try {
                                 if (this.showOverlay.getVisible() && (target === this.showOverlay.elements.overlay || target === this.showOverlay.elements.container)) {
                                 this.showOverlay.close();
                                 }
                                 } catch (err) {
                                 }
                                 */
                            }
                        } catch (err) {
                        }
                    }.bind(this),
                    'keydown': function(ev) {
                        if (ev.key === 'esc' && this.showOverlay.getVisible() === true) {
                            EFS.showOverlay.settings.close = true;

                            this.showOverlay.close();
                        }
                    }.bind(this)
                });

                EFSHelpers.console.log('Script has loaded in: ' + EFSHelpers.timer.stoping(), true);

                // load some functionality
                this.showWindow.init();
                this.showMore.init('a.' + EFS.constants.classes.showMore);
                this.forms.init($$('form'));
            }
        },
        domReady: function(callback) {
            if (document.body === false) {
                return document.setTimeout(this.DomReady(callback), 15);
            }

            callback();
            this.domInit();
        }
    };

    var EFSHelpers = {
        getTranslation: function(i18n) {
            try {
                i18n = EFSTranslate[i18n] !== undefined ? EFSTranslate[i18n] : i18n;
            } catch (err) {
            }

            return i18n;
        },
        timer: {
            fromTime: 0,

            starting: function() {
                this.fromTime = new Date();
            },
            stoping: function() {
                return ((new Date() - this.fromTime) / 1000) + 's';
            }
        },
        urlHelper: {
            setHash: function(hash) {
                if (hash !== undefined) {
                    window.location.hash = hash;
                }
            },
            removeHash: function(str) {
                str = $type(str) == 'string' && str.contains('#') ? str.substr(0, str.indexOf('#')) : str;

                return str;
            },
            addParam: function(url, param, value) {
                url = this.removeHash(url);
                url += (($type(url) == 'string') ? (url.contains('?') ? '&' : '?') + param + "=" + value : '');

                return url;
            },
            redirect: function(url) {
                if (url !== undefined) {
                    location.href = url;
                }
            },
            refresh: function() {
                this.redirect(window.location.href);
            },
            response: function(response) {
                try {
                    if (response.redirect !== undefined) {
                        this.redirect(response.redirect);
                    } else if (response.refresh === true) {
                        this.refresh();
                    }
                } catch (err) {
                }
            },
            getId: function(url) {
                if ($type(url) === 'string') {
                    var parts = url.split('/');
                    for (var i = parts.length; i >= 0; i--) {
                        var id = parseInt(parts[i], 10); // use radix - jslint
                        if (!isNaN(id)) {
                            return id;
                        }
                    }
                }

                // we expect an int
                return 0;
            }
        },
        console: {
            div: null,
            enabled: false,

            init: function() {
                try {
                    if (this.div === null && this.enabled === true) {
                        this.div = new Element('div', {
                            'id': 'efs_framework_console'
                        }).inject($$(document.body)[0], EFS.actions.where.bottom);

                        this.div.setStyles({
                            'position': 'absolute',
                            'left': 0,
                            'top': 0,
                            'width': '350px',
                            'border': '1px solid #4a4a4a',
                            'background-color': '#f9c511',
                            'color': '#000'
                        });
                    }
                } catch (err) {
                }
            },
            log: function(text, newLine) {
                this.init();

                if (this.enabled === true && this.div !== null) {
                    try {
                        this.div.setProperty('html', this.div.getProperty('html') + '<p>' + text + '</p>' + (newLine === true ? '<br>' : ''));
                    } catch (err) {
                    }
                }
            }
        }
    };

    var EFSHund = {
        notices: {
            startFunction: $empty,
            stopFunction: $empty,

            starting: function() {
                // close existing notices
                EFSHelpers.console.log('dasHund notices, started.', true);

                $clear(this.startFunction);
                $clear(this.stopFunction);

                EFS.ajax({
                    'url': '/notice'
                }, function(response) {
                    if (response.status === true) {
                        if (response.notice) {
                            // container
                            var noticeDiv = new Element('div', {
                                'id': 'actionNotice'
                            });

                            var noticeDivDiv = new Element('div');

                            noticeDiv.adopt(noticeDivDiv);
                            noticeDivDiv.setProperty('html', response.notice);

                            // close link
                            var closeA = new Element('a', {
                                'href': '#',
                                'class': 'close',
                                'html': 'close',
                                'events': {
                                    'click': function(ev) {
                                        ev = new Event(ev).stop();

                                        this.closeing();

                                        return false;
                                    }.bind(this)
                                }
                            });

                            noticeDivDiv.adopt(closeA);
                            $$(document.body)[0].adopt(noticeDiv);
                        }

                        // close after delay
                        this.stopFunction = setTimeout(function() {
                            this.closeing();
                        }.bind(this), 10000);

                        // repeat after delay
                        this.startFunction = setTimeout(function() {
                            this.starting();
                        }.bind(this), 60000);
                    }
                }.bind(this));
            },
            closeing: function() {
                if ($$('#actionNotice').length === 1) {
                    //setup tween
                    var tween = $$('#actionNotice')[0].get('tween', {
                        property: 'opacity'
                    });

                    // fade out
                    tween.start(0).chain(function() {
                        // remove notice div
                        $$('#actionNotice')[0].dispose();
                    });
                }

                EFSHelpers.console.log('dasHund notices, closeing.', true);
            },
            changeState: function(noticeId) {
                // send data
                EFS.ajax({
                    'url': '/notice/help',
                    'data': {
                        'id': noticeId
                    }
                }, function(response) {
                }.bind(this));
            },
            dasHund: function(notice) {
                var h2 = null;
                var note = notice.getNext();

                if (note !== null && note.nodeName.toLowerCase() === 'h2') {
                    h2 = note;
                }

                if (h2 === null) {
                    var note = notice.getPrevious();

                    while (note !== null) {
                        if (note.nodeName.toLowerCase() === 'h2') {
                            h2 = note;
                            break;
                        } else {
                            note = note.getPrevious();
                        }
                    }
                }

                if (h2 === null) {
                    note = notice.getNext();

                    while (note !== null) {
                        if (note.nodeName.toLowerCase() === 'h2') {
                            h2 = note;
                            break;
                        } else {
                            note = note.getNext();
                        }
                    }
                }

                var dasHund = ($type(h2) === 'element' ? h2.getElement('a.helpHund') : null);

                if ($type(dasHund) !== 'element' && h2 !== null) {
                    dasHund = new Element('a', {
                        'href': '#',
                        'html': 'helpHund',
                        'class': 'helpHund',
                        'events': {
                            'click': function(ev) {
                                ev = new Event(ev).stop();

                                if (notice.isDisplayed() === false) {
                                    notice.show();
                                    // store state on server
                                    EFSHund.notices.changeState(notice.id);

                                    dasHund.dispose();
                                }

                                return false;
                            }
                        }
                    }).inject(h2, EFS.actions.where.bottom);
                }
            }
        },
        init: function() {
            /**
             * Stripgenerator: Bug #931
             * Description: profile/library cannot close Das Hund, X button is not responding
             * Problem: #div.notice
             */
            if ($$('div.notice').length > 0) {
                $$('div.notice').each(function(notice, i) {
                    // show dasHund for hidden help notices
                    if (notice.isDisplayed() === false) {
                        EFSHund.notices.dasHund(notice);
                    }

                    notice.getChildren('a').addEvent('click', function(ev) {
                        ev = new Event(ev).stop();
                        // show dasHund
                        EFSHund.notices.dasHund(notice);

                        notice.hide();
                        // store state on server
                        EFSHund.notices.changeState(notice.id);

                        return false;
                    }.bind(this));
                });

                this.notices.starting();
            }
        }
    };

    window.EFS = window.EFS || EFS;
    window.EFSHelpers = window.EFSHelpers || EFSHelpers;
    window.EFSHund = window.EFSHund || EFSHund;

    EFSHelpers.console.log('EFS framework version: ' + EFS.version + ' with mooTools version: ' + MooTools.version, true);
    EFSHelpers.timer.starting();
})(window);

EFS.domReady(function() {
    EFSHund.init();

    EFS.bubbles('.striptistics', {
        'classes': 'bubble left'
    });
});
