/**
* @author nic
*/

/** -- Events -- **/
Element.Events.hashchange = {
    onAdd: function () {
        var hash = self.location.hash;

        var hashchange = function () {
            if (hash == self.location.hash) return;
            else hash = self.location.hash;

            var value = (hash.indexOf('#') == 0 ? hash.substr(1) : hash);
            window.fireEvent('hashchange', value);
            document.fireEvent('hashchange', value);
        };

        if ('onhashchange' in window) {
            window.onhashchange = hashchange;
        } else {
            hashchange.periodical(50);
        }
    }
};

/** -- Enums -- **/

/**
 * Page Position values TL, TR, C, BL, BR
 */
var PagePosition = { TL: 'TL', TR: 'TR', C: 'C', BL: 'BL', BR: 'BR' }

/** -- Classes -- **/

/**
 * Page sliding and data featching class
 */
var PageSlider = new Class({

    initialize: function (element) {
        this.element = $(element);
        this.isSliding = false;

        //Get pages from service
        var pageRequest = new Request.JSON({
            url: '/Services/PagesService.ashx',
            onSuccess: this.setPages.bind(this)
        }).get();

        this.attach();
    },

    setPages: function (pages) {
        this.pages = pages;
        this.page = pages[0];

        if (self.location.hash.length > 0)
            this.showPage(self.location.hash.indexOf('#') == 0 ? self.location.hash.substr(1) : self.location.hash);
    },

    attach: function () {
        window.addEvent('hashchange', this.showPage.bind(this));
    },

    showPage: function (hash) {
        var newPage = this.pages.filter(function (item) { return item.Name.test(hash.replace('!', ''), 'i'); })[0];

        if (newPage != this.page && this.isSliding == false) {
            this.page = newPage;
            this.isSliding = true;

            //Deselect links then select current
            $$('.sel').removeClass('sel');
            $$('a[href$=' + this.page.Name + ']').addClass('sel');

            var injectLocation = this.element.getElement('li#' + this.page.Position);

            if (injectLocation.get('html') == '' || this.page.Position == PagePosition.TR) {
                injectLocation.set('html', '').setStyle('background', 'transparent url("/resources/css/spinner.gif") no-repeat 50% 30%');
                //Fetch page using ajax request, then inject content
                this.fetchContentThenInject(this.page, injectLocation);
            }
            //Slide and track
            this.moveToPage();
            pageTracker._trackPageview(this.page.Url);
        }
    },

    fetchContentThenInject: function (page, injectLocation) {
        var req = new Request.HTML({
            url: page.Url,
            evalScripts: false,
            onSuccess: function (responseTree, responseElements) {
                injectLocation.setStyle("background", "");
                injectLocation.set("html", responseElements.filter("li#" + page.Position)[0].get("html"));
                if (page.Position == PagePosition.BL)
                    setupContactForm();
                if (page.Position == PagePosition.C)
                    setupHomeRollovers('/resources/images/rollover.png');
                if (page.Position == PagePosition.TR)
                    setupImageZoom();
            }
        }).get();
    },

    moveToPage: function () {
        var slideMorph = new Fx.Morph(this.element.getElement("ul#articleList"), { duration: 2500 });

        switch (this.page.Position) {
            case PagePosition.TL:
                slideMorph.start({ left: 0, top: 0 });
                break;
            case PagePosition.TR:
                slideMorph.start({ left: -1920, top: 0 });
                break;
            case PagePosition.C:
                slideMorph.start({ left: -960, top: -650 });
                break;
            case PagePosition.BL:
                slideMorph.start({ left: 0, top: -1300 });
                break;
            case PagePosition.BR:
                slideMorph.start({ left: -1920, top: -1300 });
                break;
        }
        this.isSliding = false;
    } .protect()

});


/**
 * Messaging class - hits service with a message from the contact form
 */
var ContactMessenger = new Class({

    initialize: function(senderName, senderEmail, senderMessage, serviceUrl) {
        this.senderName = senderName;
        this.senderEmail = senderEmail;
        this.senderMessage = senderMessage;
        this.serviceUrl = serviceUrl;
        this.qString = "name={name}&email={email}&message={message}";
    },

    validateMessage: function() {
        if ($chk(this.senderName) && $chk(this.senderMessage) && $chk(this.senderEmail))
            return true;
        else
            return false;
    }.protect(),

    sendMessage: function() {
        if (this.validateMessage()) {
            var userMessage = ""; //For debugging
            var myRequest = new Request({
                url: this.serviceUrl,
                onSuccess: function(responseText, responseXML) {
                    userMessage = responseText;
                    alert(userMessage);
                }
            });
            myRequest.send(this.qString.substitute({ name: this.senderName, email: this.senderEmail, message: this.senderMessage }));
        }
        else {
            alert("Sorry your message could not be sent, try emailing me instead.");
        }
    }
});


/** -- External Classes (Stuff written by great, kind people) -- **/


/**
 * ReMooz - Zoomer
 * Inspired by so many boxes and zooms
 * @version		1.0
 * @license		MIT-style license
 * @author		Harald Kirschner <mail [at] digitarald.de>
 * @copyright	Author
 */
var ReMooz = new Class({

    Implements: [Events, Options, Chain],

    options: {
        link: null,
        type: 'image',
        container: null,
        className: null,
        centered: false,
        dragging: true,
        closeOnClick: true,
        shadow: (Browser.Engine.trident) ? 'onOpenEnd' : 'onOpen', // performance
        resize: true,
        margin: 20,
        resizeFactor: 0.95,
        resizeLimit: false, // {x: 640, y: 640}
        fixedSize: false,
        cutOut: true,
        addClick: true,
        opacityLoad: 0.6,
        opacityResize: 1,
        opacityTitle: 0.9,
        resizeOptions: {},
        fxOptions: {},
        closer: true,
        parse: false, // 'rel'
        parseSecure: false,
        temporary: false,
        onBuild: $empty,
        onLoad: $empty,
        onOpen: $empty,
        onOpenEnd: $empty,
        onClose: $empty,
        onCloseEnd: $empty,
        generateTitle: function(el) {
            var text = el.get('title');
            if (!text) return false;
            var title = text.split(' :: ');
            var head = new Element('h6', { 'html': title[0] });
            return (title[1]) ? [head, new Element('p', { 'html': title[1] })] : head;
        }
    },

    initialize: function(element, options) {
        this.element = $(element);
        this.setOptions(options);
        if (this.options.parse) {
            var obj = this.element.getProperty(this.options.parse);
            if (obj && (obj = JSON.decode(obj, this.options.parseSecure))) this.setOptions(obj);
        }
        var origin = this.options.origin;
        this.origin = ((origin) ? $(origin) || this.element.getElement(origin) : null) || this.element;
        this.link = this.options.link || this.element.get('href') || this.element.get('src');
        this.container = $(this.options.container) || this.element.getDocument();
        this.bound = {
            'click': function(e) {
                this.open.delay(1, this);
                return false;
            }.bind(this),
            'close': this.close.bind(this),
            'dragClose': function(e) {
                if (e.rightClick) return;
                this.close();
            }.bind(this)
        };
        if (this.options.addClick) this.bindToElement();
    },

    destroy: function() {
        if (this.box) this.box.destroy();
        this.box = this.tweens = this.body = this.content = null;
    },

    bindToElement: function(element) {
        ($(element) || this.element).addClass('remooz-element').addEvent('click', this.bound.click);
        return this;
    },

    getOriginCoordinates: function() {
        var coords = this.origin.getCoordinates();
        delete coords.right;
        delete coords.bottom;
        return coords;
    },

    open: function(e) {
        if (this.opened) return (e) ? this.close() : this;
        this.opened = this.loading = true;
        if (!this.box) this.build();
        this.coords = this.getOriginCoordinates();
        this.coords.opacity = this.options.opacityLoad;
        this.coords.display = '';
        this.tweens.box.set(this.coords);
        this.box.addClass('remooz-loading');
        ReMooz.open(this.fireEvent('onLoad'));
        this['open' + this.options.type.capitalize()]();
        return this;
    },

    finishOpen: function() {
        this.tweens.fade.start(0, 1);
        this.drag.attach();
        this.fireEvent('onOpenEnd').callChain();
    },

    close: function() {
        if (!this.opened) return this;
        this.opened = false;
        ReMooz.close(this.fireEvent('onClose'));
        if (this.loading) {
            this.box.setStyle('display', 'none');
            return this;
        }
        this.drag.detach();
        this.tweens.fade.cancel().set(0).fireEvent('onComplete');
        if (this.tweens.box.timer) this.tweens.box.clearChain();
        var vars = this.getOriginCoordinates();
        if (this.options.opacityResize != 1) vars.opacity = this.options.opacityResize;
        this.tweens.box.start(vars).chain(this.closeEnd.bind(this));
        return this;
    },

    closeEnd: function() {
        if (this.options.cutOut) this.element.setStyle('visibility', 'visible');
        this.box.setStyle('display', 'none');
        this.fireEvent('onCloseEnd').callChain();
        if (this.options.temporary) this.destroy();
    },

    openImage: function() {
        var tmp = new Image();
        tmp.onload = tmp.onabort = tmp.onerror = function(fast) {
            this.loading = tmp.onload = tmp.onabort = tmp.onerror = null;
            if (!tmp.width || !this.opened) {
                this.fireEvent('onError').close();
                return;
            }
            var to = { x: tmp.width, y: tmp.height };
            if (!this.content) this.content = $(tmp).inject(this.body);
            else tmp = null;
            this[(this.options.resize) ? 'zoomRelativeTo' : 'zoomTo'].create({
                'delay': (tmp && fast !== true) ? 1 : null,
                'arguments': [to],
                'bind': this
            })();
        }.bind(this);
        tmp.src = this.link;
        if (tmp && tmp.complete && tmp.onload) tmp.onload(true);
    },

    /**
    * @todo Test implementation
    */
    openElement: function() {
        this.content = this.content || $(this.link) || $E(this.link);
        if (!this.content) {
            this.fireEvent('onError').close();
            return;
        }
        this.content.inject(this.body);
        this.zoomTo({ x: this.content.scrollWidth, y: this.content.scrollHeight });
    },

    zoomRelativeTo: function(to) {
        var scale = this.options.resizeLimit;
        if (!scale) {
            scale = this.container.getSize();
            scale.x *= this.options.resizeFactor;
            scale.y *= this.options.resizeFactor;
        }
        for (var i = 2; i--; ) {
            if (to.x > scale.x) {
                to.y *= scale.x / to.x;
                to.x = scale.x;
            } else if (to.y > scale.y) {
                to.x *= scale.y / to.y;
                to.y = scale.y;
            }
        }
        return this.zoomTo({ x: to.x.toInt(), y: to.y.toInt() });
    },

    zoomTo: function(to) {
        to = this.options.fixedSize || to;
        var box = this.container.getSize(), scroll = this.container.getScroll();
        var pos = (!this.options.centered) ? {
            x: (this.coords.left + (this.coords.width / 2) - to.x / 2).toInt()
				.limit(scroll.x + this.options.margin, scroll.x + box.x - this.options.margin - to.x),
            y: (this.coords.top + (this.coords.height / 2) - to.y / 2).toInt()
				.limit(scroll.y + this.options.margin, scroll.y + box.y - this.options.margin - to.y)
        } : {
            x: scroll.x + ((box.x - to.x) / 2).toInt(),
            y: scroll.y + ((box.y - to.y) / 2).toInt()
        };
        if (this.options.cutOut) this.element.setStyle('visibility', 'hidden');
        this.box.removeClass('remooz-loading');
        var vars = { left: pos.x, top: pos.y, width: to.x, height: to.y };
        if (this.options.opacityResize != 1) vars.opacity = [this.options.opacityResize, 1];
        else this.box.set('opacity', 1);
        this.tweens.box.start(vars).chain(this.finishOpen.bind(this));
        this.fireEvent('onOpen');
    },

    build: function() {
        this.addEvent('onBlur', function() {
            this.focused = false;
            this.box.removeClass('remooz-box-focus').setStyle('z-index', ReMooz.options.zIndex);
        }, true);
        this.addEvent('onFocus', function() {
            this.focused = true;
            this.box.addClass('remooz-box-focus').setStyle('z-index', ReMooz.options.zIndexFocus);
        }, true);

        var classes = ['remooz-box', 'remooz-type-' + this.options.type, 'remooz-engine-' + Browser.Engine.name + Browser.Engine.version];
        if (this.options.className) classes.push(this.options.className);
        this.box = new Element('div', {
            'class': classes.join(' '),
            'styles': {
                'display': 'none',
                'top': 0,
                'left': 0,
                'zIndex': ReMooz.options.zIndex
            }
        });

        this.tweens = {
            'box': new Fx.Morph(this.box, $merge({
                'duration': 400,
                'unit': 'px',
                'transition': Fx.Transitions.Quart.easeOut,
                'chain': 'cancel'
            }, this.options.resizeOptions)
		),
            'fade': new Fx.Tween(null, $merge({
                'property': 'opacity',
                'duration': (Browser.Engine.trident) ? 0 : 300,
                'chain': 'cancel'
            }, this.options.fxOptions)).addEvents({
                'onComplete': function() {
                    if (!this.element.get('opacity')) this.element.setStyle('display', 'none');
                },
                'onStart': function() {
                    if (!this.element.get('opacity')) this.element.setStyle('display', '');
                }
            }
		)
        };
        this.tweens.fade.element = $$();

        if (this.options.shadow) {
            if (Browser.Engine.webkit420) {
                this.box.setStyle('-webkit-box-shadow', '0 0 10px rgba(0, 0, 0, 0.7)');
            } else if (!Browser.Engine.trident4) {
                var shadow = new Element('div', { 'class': 'remooz-bg-wrap' }).inject(this.box);
                ['n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw'].each(function(dir) {
                    new Element('div', { 'class': 'remooz-bg remooz-bg-' + dir }).inject(shadow);
                });
                this.tweens.bg = new Fx.Tween(shadow, {
                    'property': 'opacity',
                    'chain': 'cancel'
                }).set(0);
                this.addEvent(this.options.shadow, this.tweens.bg.set.bind(this.tweens.bg, 1), true);
                this.addEvent('onClose', this.tweens.bg.set.bind(this.tweens.bg, 0), true);
            }
        }

        if (this.options.closer) {
            var closer = new Element('a', {
                'class': 'remooz-btn-close',
                'events': { 'click': this.bound.close }
            }).inject(this.box);
            this.tweens.fade.element.push(closer);
        }
        this.body = new Element('div', { 'class': 'remooz-body' }).inject(this.box);

        var title = this.options.title || this.options.generateTitle.call(this, this.element);
        if (title) { // thx ie6
            var title = new Element('div', { 'class': 'remooz-title' }).adopt(
			new Element('div', { 'class': 'remooz-title-bg', 'opacity': this.options.opacityTitle }),
			new Element('div', { 'class': 'remooz-title-content' }).adopt(title)
		).inject(this.box);
            this.tweens.fade.element.push(title);
        }
        this.tweens.fade.set(0).fireEvent('onComplete');

        this.drag = new Drag.Move(this.box, {
            'snap': 15,
            'preventDefault': true,
            'onBeforeStart': function() {
                if (!this.focused && !this.loading) ReMooz.focus(this);
                else if (this.loading || this.options.closeOnClick) this.box.addEvent('mouseup', this.bound.dragClose);
            }.bind(this),
            'onSnap': function() {
                this.box.removeEvent('mouseup', this.bound.dragClose);
                if (!this.options.dragging) this.drag.stop();
                else this.box.addClass('remooz-box-dragging');
            }.bind(this),
            'onComplete': function() {
                this.box.removeClass('remooz-box-dragging');
            }.bind(this)
        });
        this.drag.detach();

        this.fireEvent('onBuild', this.box, this.element);
        this.box.inject(this.element.getDocument().body);
    }

});

ReMooz.factory = function(extended) {
    return $extend(this, extended);
};

ReMooz.factory(new Options).factory({

    options: {
        zIndex: 41,
        zIndexFocus: 42,
        query: 'a.remooz',
        modal: false
    },

    assign: function(elements, options) {
        return $$(elements).map(function(element) {
            return new ReMooz(element, options);
        }, this);
    },

    stack: [],

    open: function(obj) {
        var last = this.stack.getLast();
        this.focus(obj);
        if (last && this.options.modal) last.close();
    },

    close: function(obj) {
        var length = this.stack.length - 1;
        if (length > 1 && this.stack[length] == obj) this.focus(this.stack[length - 1]);
        this.stack.erase(obj);
    },

    focus: function(obj) {
        var last = this.stack.getLast();
        obj.fireEvent('onFocus', [obj]);
        if (last == obj) return;
        if (last) last.fireEvent('onBlur', [last]);
        this.stack.erase(obj).push(obj);
    }

});


/** -- Page Functions -- **/

//Sets up contact form to be validated and send message
var setupContactForm = function() {
    //Form validator
    var contactFormValidator = new FormValidator($("aspnetForm"), { useTitles: true });

    //Send Click event handler
    $("formSubmit").removeEvents();
    $("formSubmit").addEvent("click", function(e) {
        if (contactFormValidator.validate()) {
            //If submitted data send the message
            var messenger = new ContactMessenger($("inpName").get("value"), $("inpEmail").get("value"), $("inpMessage").get("value"), "http://celinebakshi.co.uk/Services/ContactMessageService.ashx");
            messenger.sendMessage();
        }
        else {
            alert("Please fill in all the fields and enter a valid email address.");
        }
        e.stop();
    });
};

//Rollovers for homepage images
var setupHomeRollovers = function(rolloverSrc) {
    //var rollOver = new Asset.image('images/rollover.png', {id: 'rollover', title: 'rollover'});

    $$("#C article a").addEvents({
        'mouseenter': function(e) {
            var img = this.getElement("img");
            img.setStyle("background-image", "url(" + img.getAttribute('src') + ")");
            img.setAttribute("longdesc", img.getAttribute('src'));
            img.setAttribute("src", rolloverSrc);
            e.stop();
        },
        'mouseleave': function(e) {
            var img = this.getElement("img");
            var src = img.getParent("a").getAttribute("rel");
            img.setAttribute("src", src);
            img.setStyle("background-image", "url(" + rolloverSrc + ")");
            e.stop();
        }
    });
};

//Image zoomer for portfolio
var setupImageZoom = function() {
    ReMooz.assign('.imagePreview li a', {
        'origin': 'img',
        'shadow': 'onOpenEnd', // fx is faster because shadow appears after resize animation
        'resizeFactor': 0.8, // resize to maximum 80% of screen size
        'cutOut': false, // don't hide the original
        'opacityResize': 0.4, // opaque resize
        'dragging': true, // disable dragging
        'centered': true // resize to center of the screen, not relative to the source element
    });
};
