/*global jQuery*/
(function (window) {
	"use strict";
	var document = window.document,
		$ = jQuery,
		model,
		view;
	
    /**
    * Handle view
    * @namespace
    */
	view = {
		init : function () {
			/* Cufon.replace($('h1:not(.h1_logo), h2')); */

			/* Make sure the footer fills the whole bottom part of the screen */
			$(window).bind('load resize', function () {
				if ($(window).height() > $('#framework').height()) {
					$('#footer').css('height', ($('#footer').height() + ($(window).height() - $('#framework').height())) + 'px')
				} else {
					$('#footer').css('height', '');
				}
			});

			$('.news_list li, .contact_list li').addClass('clickable');
			$('.news_list li, .contact_list li').click(function (e) {
				document.location.href = $(this).find('h2 a').attr('href');
			});

			if ($.browser.webkit) {
				$('input').attr('autocomplete', 'off');
			}
			
			$("a[rel~=external], a[rel~=popup], area[rel~=external], area[rel~=popup]").live("click", function (e) {
                e.preventDefault();
				$(this).blur();
                window.open(this.href);
            });
            

		}, 

		faq : {
			init : function () {
				$('ul.faq_item li a').click(function (e) {
					e.preventDefault();
					$(this).siblings('p').toggleClass('hidden');
				});
			}
		},

        /**
        * Handle form elements
        * @base view
        * @class
        */
        form : {
            /**
            * DOM:ready invoked
            */
            init : function () {
				// Make sure the inputfields in the head is empty onload. 
				$('.login_search input[type=text], .login_search input[type=password]').val('');

                // Hide/show associated label
                $('.login_search input[type=text], .login_search input[type=password]').focus(function () {
                    $(this).prev('label:first').hide();
                }).blur(function () {
                    if ($(this).val() === '') {
                        $(this).prev('label:first').css({ display: 'inline' });
                    }
                }).keydown(function (e) {
                    if (e.keyCode === 13) {
						e.preventDefault();
						$(this).parent().find('input.button').click();
                    }
                });

				$('.login input[type=text], .login input[type=password]').keydown(function (e) {
                    if (e.keyCode === 13) {
						e.preventDefault();
						$('.contourNavigation input.button').click();
                    }
                });
            }
        },
        /**
        * Hero information box
        * @base view
        * @class 
        */
        hero : {
            /**
            * DOM:ready invoked
            */
            init : function () {
                var doSlide = function () {
                    var slider = view.hero.slider,
                        left = 0,
                        textBox = slider.data('items').eq(slider.data('currentSlide')).find('.text_box');
                    
                    // If there is a textBox present in the current slide
                    if (textBox.length) {
                        textBox.animate({
                            left: (0 - textBox.outerWidth()) + 'px'
                        }, 500);
                    }
                    // Update current slide in data
                    slider.data('currentSlide', (slider.data('currentSlide') + 1));
                    // Calculate new left property
                    left = slider.width() / slider.data('items').length * slider.data('currentSlide');
                    
                    // If on last slide, start from the beginning
                    if (left >= slider.width()) {
                        slider.data('currentSlide', 0);
                        left = 0;
                    }
                    
                    // Animate slide w/ delay for textbox
                    slider.delay(700).animate({
                        left: (0 - left) + 'px'
                    }, 500, function () {
                        // Reset textbox
                        if (textBox.length) {
                            textBox.css({ left: '0px' });
                        }
                    });
                    // Invoke new timeout
                    slider.data('slideTimeout', setTimeout(doSlide, slider.data('items').eq(slider.data('currentSlide')).find('input').val()));
                };
                // Setup new slider
                if ($('.hero_box_content ul li').length > 1) {
                    this.slider = $('.hero_box_content ul')
                    .data('items', $('.hero_box_content ul:first li'))
                    .data('currentSlide', 0)
                    .data('slideTimeout', setTimeout(doSlide, $('.hero_box_content ul:first li:first input').val()))
                    .css('width', function () {
                        var width = 0;

                        $(this).data('items').each(function (index, elem) {
                            width += parseInt($(elem).outerWidth(), 10);
                        });
    
                        return width;
                    });
                    /*.one('mouseover', function () {
                        clearTimeout($(this).data('slideTimeout'));
                    });*/
                }
            }
        }, 
        /**
        * Setup dialogs
        * @base view
        * @class
        */
        dialog : {
            /**
            * DOM:ready invoked
            */
            init : function () {
                var width = ($('body').width() - 80) > 960 ? 960 : $('body').width() - 80, //width is restricted,
					//width = $('body').width() - 80,
                    //Image need to be smaller the body size
                    diff = 22,
                    getImageSrc = function (imageSrc, imageType) {
                        if (imageSrc.match(/imagegen/i)) {
						    // Get image from image gen with new dimentions
                            if (imageType === 'png') {
                                imageSrc = imageSrc.replace(/\.jpg/, '.png');
                            }
						    imageSrc = imageSrc.replace(/width\=\d+/, 'width=' + (width - diff)).replace(/height\=\d+/, '') + '&allowupsizing=false&compression=100';
					    } else {
						    imageSrc = imageSrc.replace(/\_\d{2,4}x\d{2,4}.+/,'') + '.' + imageType;
						    /* Trubbel om man laddat upp .png istället för jpg! */
						    imageSrc = '/umbraco/ImageGen.ashx?image=' + imageSrc + '&width=' + (width - diff) + '&allowupsizing=false&compression=100';
					    }

                        return imageSrc;
                    },
                    changeImage = function (isNext) {
                        var img = this.nodeName === 'IMG' ? $(this) : $(this).siblings('img:first'),
                            imageCollection = $('#image_dialog').data('imageCollection'),
                            // get image source that could be matched to the image collection
                            currentImageSrc = img.attr('src').match(/\=[\/\w]+/g)[0].substring(1),
                            // Find image in imageCollection
                            currentImage = imageCollection.filter('img[src*=' + currentImageSrc + ']'),
                            // Get the index of next/prev image
                            nextIndex = imageCollection.index(currentImage) === 0 ? imageCollection.length - 1 : imageCollection.index(currentImage) - 1;
                                    
                        // handle previous
                        if (isNext || $(this).attr('id') === 'nextImage') {
                            nextIndex = imageCollection.index(currentImage) === imageCollection.length - 1 ? 0 : imageCollection.index(currentImage) + 1;
                        }

                        img.attr('src', (getImageSrc(imageCollection.eq(nextIndex).attr('src'), 'jpg')));
                        // Since we can't determine if it's a jpg or png, we need to see if the jpg is found
                        $.ajax({
                            url : img.attr('src'),
                            success : function (content) {
                                if (content.match(/File/g)) {
                                    img.attr('src', (getImageSrc(imageCollection.eq(nextIndex).attr('src'), 'png')));
                                }
                            }
                        });
                                        
                    }

            	$('p img.image_dialog_link').click(function () {
                    var t = $(this),
                        imageSrc = t.attr('src');
                    
                    imageSrc = getImageSrc(imageSrc, 'jpg');
                    
                    if (!$('#image_dialog').length) {
					    $('<div id="image_dialog"><!--<a id="previousImage" href="javascript:void(0)">Previous</a><a id="nextImage" href="javascript:void(0)">Next</a>--><img /></div>')
                        .data('imageCollection', $('p img.image_dialog_link'))
                        .appendTo('body').dialog({
						    autoOpen : false,
						    modal : true,
                            position : 'top',
						    open : function (event) {
							    var t = $(this),
                                    image = t.find('img');
                                    
							    image.load(function () {
                                    var img = $(this),
                                        w = img.width() + 24, // Taking in account padding on dialog
                                        h = img.height() + ((navigator.appVersion.indexOf('MSIE 7.') === -1) ? 20 : 20); // Taking in account padding on dialog
                                    
                                    // Set height and width. And trigger new positioning when setting a new postion property                                    
                                    t.dialog('option', {
                                        height : h < 80 ? 80 : h, //height is restricted
                                        width : w > 960 ? 960 : w, //width is restricted
                                        position : 'center'
                                    });
                                    // Use visibility instead of display block/hidden so img element gets height and width
                                    t.parent().css({ visibility : 'visible' });
                                    // Fix overlay ie7
                                    if (!(navigator.appVersion.indexOf('MSIE') === -1)) {
                                        $('.ui-widget-overlay').css({ width: $('body').width() + 'px' });
                                    }
                                }).attr('src', t.data('image_src')).click(changeImage);
                                
                                        
                                // Since we can't determine if it's a jpg or png, we need to see if the jpg is found
                                $.ajax({
                                    url : image.attr('src'),
                                    success : function (content) {
										if (content.match(/File/g)) {
                                            image.attr('src', (getImageSrc(image.attr('src'), 'png')));
                                        }
                                    }
                                });

                                /*$('#previousImage, #nextImage').click(changeImage);*/
                                if (!(navigator.appVersion.indexOf('MSIE 7.') === -1)) {
                                    $('.ui-dialog-titlebar').css({ margin : '0' });
                                }
								
								$(image).after('<span class="next"><a href="javascript:void(0)">Next</a></span>');
								$(image).after('<span class="prev"><a href="javascript:void(0)">Previous</a></span>');
                                
								$('.ui-dialog-titlebar a.ui-dialog-titlebar-close').attr('href', 'javascript:void(0);');
								
						    },
						    close : function (event) {
                                $(this).find('img:first').unbind('click').unbind('load');
                                $(this).parent().css({ visibility : 'hidden' });
								$('.ui-dialog #image_dialog a').remove()
						    }
					    }).parent().css({ visibility : 'hidden' });
                    }

                    $('#image_dialog').data('image_src', imageSrc).dialog('option', 'width', width).dialog('open');
					
                });

                $(document).keyup(function (event) {
                    if (event.keyCode === 37 && $('#image_dialog').length) {
                        event.preventDefault();
                        // We need to invoke changeImage in the correct scoop
                        changeImage.apply($('#image_dialog').find('img').get(0), [false]);
                    }
                    if (event.keyCode === 39 && $('#image_dialog').length) {
                        event.preventDefault();
                        // We need to invoke changeImage in the correct scoop
                        changeImage.apply($('#image_dialog').find('img').get(0), [true]);
                    }
                });
				
				$('#image_dialog span.next').live('click', function () {
                    changeImage.apply($('#image_dialog').find('img').get(0), [true]);
					$('#image_dialog span.next a').blur();
				});
				$('#image_dialog span.prev').live('click', function () {
					changeImage.apply($('#image_dialog').find('img').get(0), [false]);
					$('#image_dialog span.prev a').blur();
				});
            }
        },
        /**
        * Google Maps implementation
        */
        map : {
            /**
            * DOM:ready invoked
            */
            init : function () {
                if ($('#map_canvas').length) {
                    var lat = view.bridge.properties.lat || '78.54',
                        lng = view.bridge.properties.lng || '18.01',
                        latLng = new google.maps.LatLng(parseFloat(lat), parseFloat(lng)),
                        options = {
                            zoom: 4,
                            center: latLng,
                            mapTypeId: google.maps.MapTypeId.ROADMAP
                        },
                        map = new google.maps.Map(document.getElementById("map_canvas"), options),
                        marker = new google.maps.Marker({
                            position: latLng, 
                            map: map
                        });   
                }
            }
        },
        /**
        * Handles data transfer from .net to js via input elements.
        * @base view
        * @class 
        */
        bridge: {
            /**
            * All properties in properties object is stored with the same name as the id attribute of the input element.
            * Data is reached from $.view.bridge.properties.properties_name. ie.
            * @example $.view.bridge.properties.language_code
            * @property
            */
            properties: {},
            /**
            * Get data from .net via input elements inside #net_js_bridge element. All data is stored in the properties object.
            * Automaticlly invoked by $.runInit($.view) on dom:ready event
            */
            init: function() {
                var element;

                $('#net_js_bridge input').each(function(index, elem) {
                    element = $(elem);
                    view.bridge.properties[element.attr('id')] = element.val();
                });
            }
        }
	};
	
	/**
    * Handle Ajax request against ClientScriptService
    * @class
    */
    model = {
        /**
        * Handles the response from jQuery ajax object
        * @param {Array} data	JSON data loaded from server.
        * @param {String} queued	ID of current queue, cloud also be bool False it no queue is used.
        */
        handleResponse: function (data, queueId) {
            if (data.d.ResponseStatus !== 200) {
                this.handleError(data.d.ResponseMessage);
                return false;
            }

            if (!queueId && this.queue.tmpCallback) {
                this.queue.tmpCallback(data.d.ResponseData[0].Value);
            } else if (queueId) {
                var i = 0,
                    l = data.d.ResponseData.length,
					x;

                for (x in this.queue[queueId]) {
                    if (this.queue[queueId][x]) {
                        for (i = 0; i < l; i += 1) {
                            if (data.d.ResponseData[i].CommandName.toLowerCase() === x.toLowerCase() && this.queue[queueId][x].callback) {
                                this.queue[queueId][x].callback(data.d.ResponseData[i].Value);
                            }
                        }
                    }
                }

                model.resetQueue(queueId);
            }
        },
        /**
        * Holds queue objects. Each queue should have a unique name and contains properties with correspondant names of the name of webservice to be called.
        * Value of "WebServiceMethod" should always be false
        * @example queue1 : { WebServiceMethod : false }
        * @property
        */
        queue: {
            queue1: {
                GetTwitter: false,
                GetFriends: false
            },

            queue2: {
                AddAccount: false,
                AddSubscriber: false
            }
        },
        /**
        * Add new Queue Item to que based on queueId. If que is full. Trigger the JSON request. ie. 
        * @example model.addToQueue('que1', ['AddStuff', { name: 'stuff' }], view.removeStuff)
        * 
        * @param {String} queueId	ID of current queue, cloud also be bool False it no queue is used.
        * @param {Array} payload	Array containg Webservie name and arguments ie. ['DoStuff',  { name : 'lorem ipsum' }]
        * @param {Function} callback	Callback method, can be false if no callback is requierd 
        */
        addToQueue: function (queueId, payload, callback) {
            var queuePayload,
				i,
				queueObj = { Name: payload[0], Params: [] };

            for (i in payload[1]) {
                if (i in payload[1]) {
                    queueObj.Params.push({ Name: i, Value: payload[1][i] });
                }
            }

            if (!queueId) {
                this.queue.tmpCallback = callback;

                this.addToAjaxQueue({ request: { Commands: [queueObj]} }, false);
                return;
            } else if (this.queue[queueId][payload[0]]) {
                return false;
            }

            if (typeof this.queue[queueId] === 'undefined' || typeof this.queue[queueId][payload[0]] === 'undefined') {
                this.handleError('No queueId with the name ' + queueId + ' or the queItem ' + payload[0] + ' is not in the queue ' + queueId);
            }

            this.queue[queueId][payload[0]] = {};
            this.queue[queueId][payload[0]].payload = queueObj;
            this.queue[queueId][payload[0]].callback = callback;

            if (this.isQueueReady(queueId)) {
                queuePayload = this.getQueuePayload(queueId);
                this.addToAjaxQueue(queuePayload, queueId);
            }
        },
        /**
        * Check if queue is ready to be triggered.
        * @param {String} queueId	ID of current queue.
        * @return {Boolean}	Returns true if queue is ready.
        */
        isQueReady: function (queueId) {
            var isReady = true,
				i;

            for (i in this.queue[queueId]) {
                if (!this.queue[queueId][i]) {
                    isReady = false;
                    break;
                }
            }

            return isReady;
        },
        /**
        * Get current queues payload as and Array.
        * @param {String} queueId	ID of current queue.
        * @return {Array}	Payload array with main webservice methods as first argument.
        */
        getQueuePayload: function (queueId) {
            var payloadArray = [],
				i;

            for (i in this.queue[queueId]) {
                if (this.queue[queueId][i]) {
                    payloadArray.push(this.queue[queueId][i].payload);
                }
            }

            return { request: { Commands: payloadArray} };
        },
        /**
        * Resets the queue of current queueId.
        * @param {String} queueId	ID of current queue.
        */
        resetQueue: function (queueId) {
            var i;
            for (i in this.queue[queueId]) {
                if (this.queue[queueId][i]) {
                    this.queue[queueId][i] = false;
                }
            }
        },
        /**
        * Setup ajax properties for new ajax request.
        * @param {Array} payload	Array to be posted to webservice.
        * @param {String} queueId	ID of current queue.
        */
        addToAjaxQueue: function (payload, queueId) {
            var ajaxOptions = {
                url: '/ScriptServices/ClientDataTransferService.asmx/GetData',
                type: 'post',
                dataType: 'json',
                contentType: 'application/json',
                data: JSON.stringify(payload),
                callback: queueId,
                success: function (data) {
                    var arg = [data, this.callback];
                    model.handleResponse.apply(model, arg);
                },
                error: model.handleError
            };

            this.doJsonPost(ajaxOptions);
        },
        /**
        * Array to hold currently running ajax requests
        * @property
        */
        ajaxQueue: [],

        /**
        * Triggers jQuery's ajax method and triggers handleResponse method passing loaded data and queId.
        * Uses this.ajaxQueue queue to keep ajax request to be invoked in proper order.
        * @param {Object} ajaxOptions Object containing properties of ajax request.
        */
        doJsonPost: function (ajaxOptions) {
            var ajaxQueueItem,
                ajaxCall = (function (ajaxOptions, obj) { //Return anonymouse function to keep context of ajaxOpotions and obj.
                    return function () {
                        var onSuccess = ajaxOptions.success,
                            ajaxQueue = obj.ajaxQueue;
                        // Override succuess function in ajaxOptions to add logic for handling ajaxQueue
                        ajaxOptions.success = function () {
                            if (onSuccess) {
                                onSuccess.apply(obj, arguments);
                            }

                            ajaxQueue.shift();

                            if (ajaxQueue.length > 0) {
                                ajaxQueueItem = obj.ajaxQueue[0];
                                ajaxQueueItem();
                            }
                        };
                        $.ajax(ajaxOptions);
                    };
                }(ajaxOptions, this));
            //Add new Ajax call to queue
            this.ajaxQueue.push(ajaxCall);
            //If ajax queue is empty or contain only a singel call, invoke it.
            if (this.ajaxQueue.length <= 1) {
                ajaxQueueItem = this.ajaxQueue[0];
                ajaxQueueItem();
            }
        },
        /**
        * Throws error from jQuery ajax method.
        */
        handleError: function (err) {
            throw new Error(err);
        }
    };
	
	$.extend({ view: view });
	
	$(document).ready(function () {
		$.runInit($.view);
	});
	
}(window));

