var jsCore = jsCore || {};

jsCore.Base = new Class({

    Implements: Options,

    helperInstance: null,

    /**
     * Constructor
     */
    initialize: function (options, iOptions) {
        (iOptions !== false && typeOf(options) == 'object') && this.setOptions(options);
    },

    /**
     * initialize jsCore
     */
    init: function (config) {
        jsCore.Config = config;
        jsCore.Helper = new jsCore.Helpers();
        return jsCore;
    },

    /**
     * Class loader
     */
    load: function () {
        jsCore.Class = [];

        Array.from(arguments).each(function (argument) {
            if (typeOf(window[argument[0]]) == 'class') {
                // Callback to class executer
                var extension = function () {
                    jsCore.Class[argument[0]] = new window[argument[0]](argument[1] || {});
                };
                // If need call class after domready event
                if (argument[1] && argument[1].domready === true) {
                    window.addEvent('domready', extension);
                } else {
                    // Call at once
                    extension.call();
                }
            } else {
                throw new Error('Class: ' + argument[0] + ' not exist');
            }
        });
        
        return this;
    },

    /**
     * Return internal parameter on father class
     */
    iGet: function () {
        var section = arguments[0].match(/^(.*?)::(.*)$/);

        if (!section) {
            throw new Error('Incorrect call base getter method');
        }
        
        switch (section[1]) {
            case 'text':
                return typeof(arguments[1]) == 'object' ? this.options.texts[section[2]].substitute(arguments[2]) : this.options.texts[section[2]];
                break;
            case 'class':
                return this.options.classes[section[2]];
                break;
            case 'object':
                return this.options.objects[section[2]];
                break;
            case 'lang':
                return this.parceOption(key, arguments[2] || globalDynamicLang || {});
                break;
            case 'option':
                return this.parceOption(key, arguments[2] || coreOptions || {});
                break;
            case 'helper':
                if (typeOf(this.helperInstance[section[2]]) != 'function') {
                    throw new Error('Helper: ' + section[2] + ' not exist');
                }
                return this.helperInstance[section[2]].apply(this.helperInstance, Array.from(arguments).slice(1).flatten());
                break;
        }
    },

    /**
     * Parce multiple config value
     */
    parceOption: function (key, store) {
        var propertyName,
        keyArray = key.split("::");
        for (var segment in keyArray) {
            if (keyArray.hasOwnProperty(segment)) {
                propertyName = propertyName == null ? store[keyArray[segment]] : propertyName[keyArray[segment]];
                if (propertyName === undefined) {
                    throw new Error('Error getting section name: ' + keyArray[segment]);
                }
            }
        }
        return propertyName;
    }
    
});


jsCore.Helpers = new Class({

    Extends: jsCore.Base,

    elements: {},

    initialize: function () {
        return this;
    },

    go: function (param) {
        window.location.href = param;
    },

    isValidMail: function (str) {
        return str.match(/\b(^(\S+@).+((\.com)|(\.net)|(\.edu)|(\.mil)|(\.gov)|(\.org)|(\..{2,2}))$)\b/gi);
    },

    isValidUrl: function (str) {
        return str.test(/(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/)
    },

    searchSubmit: function (elements) {
        this.grabObjects(this.elements, elements);
       
        var fx = new Fx.Tween(this.elements.container.getElement('form input[type=submit]'), {
            'transition': 'pow:out',
            'link': 'cancel'
        });

        this.elements.container.getElement('form').addEvent('submit', function (e) {
            if (this.elements.container.getElement('form input[type=text]').getProperty('value') == '' || this.elements.container.getElement('form input[type=text]').getProperty('value') == 'SEARCH') {
                alert('Search string must be specified');
                e.stop();
                return false;
            }
        }.bind(this));
        
        this.elements.container.getElement('form input[type=text]').addEvents({
            'focus':function () {
                fx.start('background-position', '1px 3px');
            },
            'blur':function () {
                fx.start('background-position', '20px 3px');
            }
        });
    }
});


var slideShow = new Class({
    
    Extends: jsCore.Base,

    elements: {
        controllElement: [],
        imageElement: []
    },
    active: 0,
    autoslide: 0,
    timer: null,
    loaderTimer: null,
    idle: false,

    options: {
        'autochange': {
            'enable': true,
            'interval': 2000
        },
        'colors': {
            'activeSquare': '#A8A8A8',
            'unactiveSquare': '#FFF'
        },
        'imageobserver': {
            'enable': true,
            'interval': 300
        },
        'classes': {
            'active': 'active'
        }

    },

    initialize: function(options) {
        this.parent(options);
        this.grabObjects(this.elements, this.options.objects);
        this.images = this.options.images;
    },

    start: function () {
        // No images - no slideshow
        if (this.images.length == 0) return false;
        this.attachControlls();
        this.attachImages();
        this.autoChange();
    },

    autoChange: function () {
        if (this.options.autochange.enable === false) return false;
        
        this.timer = setInterval(function() {
            this.autoslide = (this.autoslide < this.images.length - 1) ? this.autoslide + 1 : 0;
            this.changeSlide(this.autoslide, false);
        }.bind(this), this.options.autochange.interval);
    },

    attachImages: function () {
        this.images[0] = this.elements.imageElement[0] = this.elements.container.getElement('img');
        Array.each(this.images, function (data, index) {
            if (index > 0) {
                this.elements.imageElement[index] = new Element('img', {
                    'src': data,
                    'styles': {
                        'opacity': 0
                    }
                }).inject(this.elements.container);
            }
            this.elements.imageElement[index].store('fx', new Fx.Tween(this.elements.imageElement[index], {
                link: 'cancel'
            }));
            if (this.options.imageobserver.enable === true) {
                this.elements.imageElement[index].addEvent('load', function () {
                    this.elements.imageElement[index].store('loaded', true);
                }.bind(this));
            }
        }, this);
    },

    imageObserver: function (slide, callback) {
        if (this.elements.imageElement[slide].retrieve('loaded') == null) {
            this.elements.loader.fade(1);
            this.elements.controllButtons.fade(0)

            this.loaderTimer = setInterval(function () {
                if (this.elements.imageElement[slide].retrieve('loaded') == true) {
                    clearInterval(this.loaderTimer);
                    this.elements.loader.fade(0);
                    this.elements.controllButtons.fade(1);
                    this.idle = false;
                    callback.attempt(this);
                }
            }.bind(this), this.options.imageobserver.interval);
            return false;
        } 
    },

    changeSlide: function (slide, manually) {
        if (this.active == slide || this.idle) return false;
        this.idle = true;

        if (this.options.imageobserver.enable === true && this.imageObserver(slide, this.changeSlide.bind(this, slide, manually)) === false) return false;

        clearInterval(this.timer);

        this.markActiveControll(slide);

        this.elements.imageElement[slide].retrieve('fx').start('opacity', 1).chain(function () {
            this.idle = false;
            if (manually) {
                this.autoslide = slide;
            }
            this.autoChange();
        }.bind(this));
        this.elements.imageElement[this.active].retrieve('fx').start('opacity', 0);
        this.active = slide;
    },

    markActiveControll: function (slide) {
        this.elements.controllElement[this.active].retrieve('fx').start('background-color', this.options.colors.unactiveSquare);
        this.elements.controllElement[slide].retrieve('fx').start('background-color', this.options.colors.activeSquare);
    },

    attachControlls: function () {
        this.elements.controllButtons =  new Element('UL');
        Array.each(this.images, function (data, index) {
            this.elements.controllElement[index] = new Element('LI', {
                'class': index == 0 ? this.iGet('class::active'): '',
                'events': {
                    'click': this.changeSlide.bind(this, index, true)
                }
            }).inject(this.elements.controllButtons);

            this.elements.controllElement[index].store('fx', new Fx.Tween(this.elements.controllElement[index], {
                link: 'cancel'
            }));
        }, this);
        this.elements.controllButtons.inject(this.elements.controll);
    }
});

var expandableMenu = new Class({
    Extends: jsCore.Base,

    elements: {},
    opened: null,
    
    options: {
        'classes': {
            'active': 'color-4'
        }
    },

    initialize: function(options) {
        this.parent(options);
        this.grabObjects(this.elements, this.options.objects);
        this.findExpandable();
    },

    findExpandable: function () {
        this.elements.container.getElements('li[rel=has-child]').each(function (liElement) {
                   
            var childElement = liElement.getElement('ul.child');

            // FF can't correctly determine height of block when using spec fonts
            var charMultiplier = (Browser.firefox3 && Browser.Platform.win) ? 1.27 : 1;

            childElement.store('fx', new Fx.Tween(childElement, {
                'transition': Fx.Transitions.Pow.easeOut,
                'duration': 450
            })).store('full-height', (childElement.getStyle('height').toInt() / charMultiplier) + 'px');

            if (liElement.hasClass('active') === false) { 
                childElement.setStyle('height', 0);
            } else {
                liElement.getElement('a').addClass(this.iGet('class::active'));
                this.opened = childElement;
            }

            liElement.addEvent('click', this.expandMenu.bind(this, childElement));

        }, this);
    },

    expandMenu: function (element) {
        if (this.opened && this.opened != element) {
            this.opened.retrieve('fx').start('height', '0px');
            this.opened.getPrevious('a').removeClass(this.iGet('class::active'));
            this.opened.store('state', 'closed');
        }
        
        this.opened = element;

        element.getPrevious('a').addClass(this.iGet('class::active'));
        element.retrieve('fx').start('height', element.retrieve('full-height'));
        element.store('state', 'opened');
    
    }
});




var popapWindow = new Class({
    Extends: jsCore.Base,
    Implements: Events,

    elements: {},
    state: 'hidden',
    mask: null,

    options: {
        'mask': {
            'enable': true,
            'style': 'window-mask'
        },
        'popap': {
            'closeByEsc': true,
            'width': '500px',
            'height': '300px'
        },
        'classes': {
            'container': 'popap-window',
            'wraper': 'popap-window-wraper',
            'close': 'popap-window-close-button'
        }
    },

    initialize: function(options) {
        this.parent(options);
        this.grabObjects(this.elements, this.options.objects);
        this.buildHTML();
        if (this.options.mask.enable) {
            this.mask = new Mask({
                'class': this.options.mask.style
            });
        }

        // Close popap when escape key pressed
        window.addEvent('keydown', function(e){
            e.key == 'esc' && this.options.popap.closeByEsc && this.hide();
        }.bind(this));

        // Change popap position if window is scrolled or resized
        window.addEvents({
            'scroll': this.reposition.bind(this),
            'resize': this.reposition.bind(this)
        });
    },

    reposition: function () {
        if (this.state == 'hidden') {
            return false;
        }
        var position = this.getPosition();
        this.container.retrieve('fx').start({
            'top': position.top,
            'left': position.left
        });

    },

    buildHTML: function () {
        this.container = new Element('DIV', {
            'class': this.iGet('class::container'),
            'styles': {
                'width': this.options.popap.width.toInt() + 11,
                'height': this.options.popap.height.toInt() + 11
            }
        }).inject(document.id(document.body));

        this.wraper = new Element('DIV', {
            'class': this.iGet('class::wraper'),
            'styles': {
                'width': this.options.popap.width.toInt(),
                'height': this.options.popap.height.toInt()
            }
        }).inject(this.container);

        this.close = new Element('DIV', {
            'class': this.iGet('class::close'),
            'events': {
                'click': this.hide.bind(this)
            }
        }).inject(this.container);

        this.container.store('fx', new Fx.Morph(this.container, {
            'transition': Fx.Transitions.Expo.easeOut,
            'link': 'cancel'
        }));
    },

    getPosition: function () {
        return this.container.position({
            'position': 'center',
            'returnPos': true,
            'offset': {
                'x': 11,
                'y': -11
            }
        });
    },

    show: function () {
        this.mask.show();
        var position = this.getPosition();
        this.container.setStyles(
            Object.merge(this.getPosition(), {
                'display': 'block'
            }));
        this.container.retrieve('fx').set({
            'opacity': 0
        }).start({
            'top': [position.top - 50, position.top],
            'opacity': 1
        }).chain(function () {
            this.state = 'visible';
        }.bind(this));

    },

    hide: function () {
        this.mask.hide();
        this.fireEvent('onHideStart');
        var position = this.getPosition();
        this.container.retrieve('fx').set({
            'opacity': 1
        }).start({
            'top': [position.top, position.top + 50],
            'opacity': 0
        }).chain(function () {
            this.container.setStyle('display', 'none');
            this.state = 'hidden';
            this.fireEvent('onHideFinish');
        }.bind(this));
    }
});

popapWindow.Element = new Class({
    Extends: popapWindow,

    initialize: function(selector, options) {
        this.parent(options);
        this.data = document.getElement(selector);
        if (typeOf(this.data) == 'element') {
            this.data.inject(this.wraper);
        } else {
            throw new Error('Cannot find element with given selector');
        }
    },

    show: function () {
        this.parent();
        this.data.setStyles({
            'display': 'block',
            'visibility': 'visible'
        });
    }
});


var formParser = new Class({
    Implements: Options,

    formHash: new Hash(),
    keyCache: new Hash(),
    
    options: {
        ignoreEmpty: false,
        filterName: [],
        filterElement: []
    },
    initialize: function(el,options) {
        this.setOptions(options);
        this.form = document.id(el);
        this.formHash.empty();
        return this.parse();
    },
    getPair: function (key) {
        var splName = key.match(/(\S+)\[(|\w+)\]/);
        return !!(splName || splName === 0) ? {
            'v': splName[1],
            'p': true,
            's': splName[2]
        } : {
            'v': key,
            'p': false,
            's': null
        }
    },
    getPairName: function (key) {
        if (!!(this.getPair(key).s || this.getPair(key).s === 0)) {
            return this.getPair(key).s;
        }
        else {
            var name = this.keyCache.get(this.getPair(key).v)+1;
            this.keyCache.set(this.getPair(key).v,name);
            return name;
        }
    },
    setPair: function (k,v) {
        if (!!!(k || k === 0) || (this.options.ignoreEmpty && !!!(v || v === 0))) return;
        if (this.options.filterName.length > 0 && this.options.filterName.indexOf(this.getPair(k).v) == -1) return;
        if (!this.keyCache.has(this.getPair(k).v)) this.keyCache.set(this.getPair(k).v,-1);
        if (this.getPair(k).p && this.formHash.has(this.getPair(k).v) && typeOf(this.formHash.get(this.getPair(k).v)) == 'array')
            this.formHash.get(this.getPair(k).v).push({
                'key': this.getPairName(k),
                'value': v
            });
        else if (this.getPair(k).p)
            this.formHash.set(this.getPair(k).v,[{
                'key': this.getPairName(k),
                'value': v
            }]);
        else
            this.formHash.set(this.getPair(k).v,v);
    },
    parse: function () {
        var allElements = this.form.getElements("input,select,textarea");
        allElements.each(function (e) {
            if (this.options.filterElement.length > 0 && this.options.filterElement.indexOf(e.type) == -1) return;
            switch (e.type) {
                case 'text':
                case 'password':
                case 'hidden':
                case 'textarea':
                case 'submit':
                    this.setPair(e.get('name'),e.get('value'));
                    break;
                case 'radio':
                case 'checkbox':
                    if (e.get('value') != false && e.get('checked') != false) this.setPair(e.get('name'),e.get('value'));
                    break;
                case 'select-one':
                    this.setPair(e.get('name'),e.get('value'));
                    break;
                case 'select-multiple':
                    e.get('value').each(function (xPc) {
                        this.setPair(e.get('name'),xPc);
                    },this);
                    break;
            }
        },this);
        return this.formHash;
    }
});

var authorizationBasic = new Class({
    Extends: jsCore.Base,

    elements: {},
    fx: {},
    request: null,
    popap: {},

    options: {
        'objects': {},
        'classes': {
            'caption': 'caption',
            'normal': 'color-5',
            'error': 'color-3',
            'sucess': 'color-6',
            'loader': 'loader'
        },
        'texts': {
            'promptMsg': 'Please enter your contact information to register',
            'filledError': 'Registration error. You should fill all fields',
            'mailError': 'You entered an incorrect e-mail. Please try again',
            'processingLogin': 'Processing... Please wait',
            'userAlreadyRegister': 'User already registered. Choose another username',
            'mailAlreadyRegister': 'This e-mail address already used by other user',
            'sucessRegister': 'Successfully registered',

            'loginEmptyField': 'Login error. Please enter your login & password',
            'loginWrong': 'You have entered invalid username or password',
            'loginNoActive': 'Your account is not activated',
            'authorizedSucess': 'You have successfully authorized.',
            'promptMsgLogin': 'Please enter your username & password to login'
        }
    },
    
    initialize: function(options) {
        this.parent(options);
        this.grabObjects(this.elements, this.options.objects);
        this.attachEvents();
        this.popap.login = new popapWindow.Element(this.elements.loginform, {
            'popap': {
                'width': '300px',
                'height': '170px'
            },
            'onHideFinish': function () {
                this.restoreLoginForm();
            }.bind(this)

        });

        this.popap.register = new popapWindow.Element(this.elements.registerform, {
            'popap': {
                'width': '300px',
                'height': '290px'
            },
            'onHideFinish': function () {
                this.restoreRegisterForm();
            }.bind(this)
        });
    },

    attachEvents: function () {
        // Captions
        try {
            this.elements.control.getElement('a[rel=login]').addEvent('click', function (e) {
                e.stop();
                this.popap.login.show();
            }.bind(this));

            this.elements.control.getElement('a[rel=register]').addEvent('click', function (e) {
                e.stop();
                this.popap.register.show();
            }.bind(this));
        } catch (e) {}

        // Process actions
        this.elements.loginform.getElement('form').addEvent('submit', function (e) {
            e.stop();
            this.processLoginForm();
        }.bind(this));

        this.elements.registerform.getElement('form').addEvent('submit', function (e) {
            e.stop();
            this.processRegisterForm();
        }.bind(this));

        // Register next-action - close
        this.elements.registerform.getElement('input[rel=close]').addEvent('click', function (e) {
            e.stop();
            this.popap.register.hide();
        }.bind(this));
    },
    
    processLoginForm: function () {
        var form = new formParser(this.elements.loginform.getElement('form'));

        for (var element in form) {
            if (form.hasOwnProperty(element) && form[element] == '') {
                return this.setErrorMessage(this.elements.loginform.getElement('div.' + this.iGet('class::caption') + ' div'), this.iGet('class::error'), this.iGet('text::loginEmptyField'));
            }
        }
        this.setErrorMessage(this.elements.loginform.getElement('div.' + this.iGet('class::caption') + ' div'), this.iGet('class::normal'), this.iGet('text::processingLogin'));
        this.elements.loginform.getElement('div.' + this.iGet('class::loader')).setStyle('visibility', 'visible');
        this.request = new Request.JSON({
            url: jsCore.Config.path.base + '/?ajax_login=1',
onComplete: function (json) {
                if (!json) return false;
                this.elements.loginform.getElement('div.' + this.iGet('class::loader')).setStyle('visibility', 'hidden');
                if (json.error == 1) {
                    return this.setErrorMessage(this.elements.loginform.getElement('div.' + this.iGet('class::caption') + ' div'), this.iGet('class::error'), this.iGet('text::loginWrong'));
                } else if (json.no_actived == 1) {
                    return this.setErrorMessage(this.elements.loginform.getElement('div.' + this.iGet('class::caption') + ' div'), this.iGet('class::error'), this.iGet('text::loginNoActive'));
                } else if (json.sucess == 1) {
                    this.elements.loginform.getElement('form').setStyle('display', 'none');
                    this.popap.login.container.retrieve('fx').start({
                        'height': '60px'
                    });
					window.location.reload();
                    /*this.setErrorMessage(this.elements.loginform.getElement('div.' + this.iGet('class::caption') + ' div'), this.iGet('class::sucess'), this.iGet('text::authorizedSucess'), function () {
                        (function () {
                            window.location.reload();
                        }).delay(1000)
                    });*/
                }
            }.bind(this)
        }).POST(form);
    },

    processRegisterForm: function () {
        var form = new formParser(this.elements.registerform.getElement('form'));
        
        for (var element in form) {
            if (form.hasOwnProperty(element) && form[element] == '') {
                return this.setErrorMessage(this.elements.registerform.getElement('div.' + this.iGet('class::caption') + ' div'), this.iGet('class::error'), this.iGet('text::filledError'));
            }
        }

        if (jsCore.Helper.isValidMail(form.usermail) === null) {
            return this.setErrorMessage(this.elements.registerform.getElement('div.' + this.iGet('class::caption') + ' div'), this.iGet('class::error'), this.iGet('text::mailError'));
        }

        this.elements.registerform.getElement('div.' + this.iGet('class::loader')).setStyle('visibility', 'visible');
        this.setErrorMessage(this.elements.registerform.getElement('div.' + this.iGet('class::caption') + ' div'), this.iGet('class::normal'), this.iGet('text::processingLogin'));
        this.request = new Request.JSON({
            url: jsCore.Config.path.base + '/?ajax_register=1',
            onComplete: function (json) {
                if (!json) return false;
                this.elements.registerform.getElement('div.' + this.iGet('class::loader')).setStyle('visibility', 'hidden');
                if (json.user_already_registered == 1) {
                    return this.setErrorMessage(this.elements.registerform.getElement('div.' + this.iGet('class::caption') + ' div'), this.iGet('class::error'), this.iGet('text::userAlreadyRegister'));
                }
                if (json.mail_already_registered == 1) {
                    return this.setErrorMessage(this.elements.registerform.getElement('div.' + this.iGet('class::caption') + ' div'), this.iGet('class::error'), this.iGet('text::mailAlreadyRegister'));
                }
                this.elements.registerform.getElement('form').setStyle('display', 'none');
                this.popap.register.container.retrieve('fx').start({
                    'height': '120px'
                }).chain(function () {
                    this.elements.registerform.getElement('div.next-action').setStyles({
                        'display': 'block',
                        'opacity': 0
                    }).fade(1);
                }.bind(this));
                this.setErrorMessage(this.elements.registerform.getElement('div.' + this.iGet('class::caption') + ' div'), this.iGet('class::sucess'), this.iGet('text::sucessRegister'));
                   
          
            }.bind(this)
        }).POST(form);
    },

    restoreRegisterForm: function () {
        this.request && this.request.cancel();
        this.fx.caption && this.fx.caption.cancel();
        this.elements.registerform.getElement('div.' + this.iGet('class::loader')).setStyle('visibility', 'hidden');
        this.elements.registerform.getElements('form input[type=text], form input[type=password]').setProperty('value', '');
        this.elements.registerform.getElement('form').setStyle('display', 'block');
        this.elements.registerform.getElement('div.next-action').setStyle('display', 'none');
        this.setErrorMessage(this.elements.registerform.getElement('div.' + this.iGet('class::caption') + ' div'), this.iGet('class::normal'), this.iGet('text::promptMsg'));
        this.popap.register.container.retrieve('fx').set({
            'height': '290px'
        })
    },

    restoreLoginForm: function () {
        this.request && this.request.cancel();
        this.fx.caption && this.fx.caption.cancel();
        this.elements.loginform.getElement('div.' + this.iGet('class::loader')).setStyle('visibility', 'hidden');
        this.elements.loginform.getElements('form input[type=text], form input[type=password]').setProperty('value', '');
        this.elements.loginform.getElement('form').setStyle('display', 'block');
        this.setErrorMessage(this.elements.loginform.getElement('div.' + this.iGet('class::caption') + ' div'), this.iGet('class::normal'), this.iGet('text::promptMsgLogin'));
        this.popap.login.container.retrieve('fx').set({
            'height': '170px'
        })
    },

    setErrorMessage: function (element, style, text, callback) {
        if (element.get('html') == text && element.className.contains(style)) return false;
        if (typeOf(this.fx.caption) != 'object') {
            this.fx.caption = new Fx.Tween(element, {
                'link': 'chain',
                'transition': Fx.Transitions.Pow.easeOut,
                'duration': 350
            });
        }
        this.fx.caption.start('left', element.getStyle('width')).chain(function () {
            element.className = style;
            element.set('html', text);
            this.start('left', ['-' + element.getStyle('width'), '0px']).chain(function () {
                typeOf(callback) == 'function' && callback.attempt(this);
            })
        });
    }
});



var imageManager = new Class({
    Extends: jsCore.Base,

    elements: {},
    image: [],
    idle: false,

    options: {
        'objects': {},
        'classes': {
            'loader': 'loader'
        }
    },

    initialize: function(options) {
        this.parent(options);
        this.grabObjects(this.elements, this.options.objects);
        this.buildHTML();
        this.attachEvents();
    },

    buildHTML: function () {
        this.elements.loader = new Element('div', {
            'class': this.iGet('class::loader')
        }).inject(this.elements.container);
    },

    attachEvents: function () {
        this.elements.container.getElements('img').each(function (imgElement) {
            imgElement.store('fx', new Fx.Tween(imgElement, {
                'link': 'cancel'
            }));
            imgElement.addEvent('click', this.insert.bind(this, imgElement));
        }, this);
    },

    loader: function (element, state) {
        var coord = element.getCoordinates(),
        display = {
            'show': 'block',
            'hide': 'none'
        };

        this.elements.loader.setStyles({
            'left': coord.left + (coord.width / 2) - 8,
            'top': coord.top + coord.height + 8
        });

        this.elements.loader.setStyle('display', display[state]);
    },

    insert: function (element) {
        if (this.idle) return false;
        this.idle = true;
        var id = element.get('rel');
        
        if (this.image[id]) {
            this.elements.source.setProperty('src', this.image[id].src);
            this.idle = false;
        } else {
            element.retrieve('fx').start('opacity', 0.5);
            this.loader(element, 'show');
            this.load(id, function () {
                element.retrieve('fx').start('opacity', 1);
                this.loader(element, 'hide');
                this.idle = false;
                this.insert(element, id);
            });
        }
    },

    load: function (id, callback) {
        this.image[id] = new Element('img', {
            'src': jsCore.Config.path.base + '/products-services/images/' + id,
            'styles': {
                'position': 'absolute',
                'left': '-1000px',
                'top': '-1000px'
            },
            'events': {
                'load': callback.bind(this)
            }
        }).inject(document.body);
    }
});

var contactForm = new Class({
    Extends: jsCore.Base,

    elements: {},
    idle: false,

    options: {
        'objects': {},
        'classes': {
            'message': 'form-message',
            'loading': 'form-message-loading',
            'error': 'form-message-error',
            'sucess': 'form-message-sucess'
        },
        'texts': {
            'loading': 'Sending. Please wait',
            'error': 'Sending error. You should fill all fields',
            'sucess': 'Message sent successfully',
            'fail': 'Internal sending error. Try again later'
        }
    },

    initialize: function(options) {
        this.parent(options);
        this.grabObjects(this.elements, this.options.objects);
        this.elements.form = this.elements.container.getElement('form');
        this.buildHTML();
        this.attachEvents();
    },

    buildHTML: function () {
        this.elements.message = new Element('DIV', {
            'class': this.iGet('class::message')
        }).inject(this.elements.form);
    },

    attachEvents: function () {
        this.elements.form.addEvent('submit', function (e) {
            e.stop();
            this.process();
        }.bind(this));
    },

    process: function () {
        if (this.idle) return false;
        this.idle = true;
        var form = new formParser(this.elements.form);
        for (var element in form) {
            if (form.hasOwnProperty(element) && form[element] == '') {
                this.idle = false;
                return this.setMessage('show', this.iGet('text::error'), this.iGet('class::error'));
            }
        }

        this.setMessage('show', this.iGet('text::loading'), this.iGet('class::loading'));
        this.request = new Request.JSON({
            url: jsCore.Config.path.base + '/?ajax_contact=1',
            onComplete: function (json) {
                if (!json) return false;
                this.idle = false;
                if (json.result == 1) {
                    this.setMessage('show', this.iGet('text::sucess'), this.iGet('class::sucess'));
                    this.elements.form.getElements('input[type=text]').setProperty('value', '');
                } else {
                    this.setMessage('show', this.iGet('text::fail'), this.iGet('class::error'));
                }
            }.bind(this)
        }).POST(form);
    },

    setMessage: function (action, text, className) {
        var display = {
            'show': 'block',
            'hide': 'none'
        };
        this.elements.message.setStyle('display', display[action]);

        this.elements.message.set('html', text);
        if (className) {
            this.elements.message.className = className;
        }
    }

});


var contactMap = new Class({
    Extends: jsCore.Base,

    elements: {},

    options: {
        objects: {}
    },

    initialize: function(options) {
        this.parent(options);
        this.grabObjects(this.elements, this.options.objects);
        this.create();
        this.marker();
    },

    create: function () {
        this.map = new GMap2(this.elements.container);
        this.map.addControl(new GSmallZoomControl3D());
        this.map.setCenter(new GLatLng(this.options.map[0], this.options.map[1]), this.options.zoom);
    },

    marker: function () {
        this.markerLatitude = new GLatLng(this.options.marker[0], this.options.marker[1]);

        this.marker = new GMarker(this.markerLatitude);
        this.map.addOverlay(this.marker);

        GEvent.addListener(this.marker, "click", function() {
            this.map.openInfoWindowHtml(this.markerLatitude, this.options.text);
        }.bind(this));
    }
});

var placeholder = new Class({
    Extends: jsCore.Base,

    options: {
        elements: 'input[type=text]',
        cssClass: 'placeholder',
        color: null
    },
    initialize: function(options)  {
        this.parent(options);

        var elements = null;
        switch (typeOf(this.options.elements))
        {
            case 'string':
                elements = document.getElements(this.options.elements);
                break;
            case 'element':
                elements = [this.options.elements];
                break;
            default:
                elements = this.options.elements;
        }

        elements.each(function(el){
            var text = el.get('placeholder');
            if (text)  {
                el.store('ns-placeholder-text', text);
                el.store('ns-placeholder-color', el.getStyle('color'));

                this.blur(el);

                el.addEvents({
                    focus: function(){
                        this.focus(el);
                    }.bind(this),
                    blur: function(){
                        this.blur(el);
                    }.bind(this)
                });

                var form = el.getParent('form');
                if (form)
                {
                    form.addEvent('submit', function()
                    {
                        if (el.value == text)
                            el.set('value', '');
                    });
                }
            }
        }.bind(this));
    },

    focus: function(el, focus) {
        focus = focus == undefined || focus;

        var text = el.retrieve('ns-placeholder-text'),
        value = el.get('value');

        if (value == '' || value == text)
        {
            if (this.options.cssClass)
                el[focus ? 'removeClass' : 'addClass'](this.options.cssClass);

            if (this.options.color)
                el.setStyle('color', focus ? el.retrieve('ns-placeholder-color') : this.options.color);

            el.set('value', focus ? '' : text);
        }
    },

    blur: function(el)  {
        this.focus(el, false);
    }
});







