/**
 * enhancements.js
 */
 
/*jslint browser: true, rhino: true, newcap: false, maxlen:78 */

 /* All globals*/
/*globals window, $, console, navigator, GUnload, GBrowserIsCompatible, GMap2,
GLatLngBounds, GLatLng, GMarker, google*/
  
 /* JavaScript */
/*member match, console, hasOwnProperty, prototype, push, userAgent, 
onunload, test, round, replace, appVersion, max, unshift, call, abs*/

/* CSS */
/*member 'margin-top', 'margin-right', 'margin-bottom', 'margin-left', left
float, bottom, position, top, opacity*/

/* jQuery */
/*member after, andSelf, attr, blur, click, closest, css, each, filter, find,
focus, hide, html, log, next, nextUntil, parents, prepend, submit, text,
title, val, wrap, append, not, wrapAll, parent, width, height, clone, filter,
length, children, removeClass, addClass, animate, hasClass, remove

/* Google Maps*/
/*member, setUIToDefault, marker, hide, extend, bindInfoWindowHtml, overlay,
addOverlay, setCenter, getCenter, setZoom, getBoundsZoomLevel */

$(function() {
    
    window.log = function(str) {
        if(window.console && console.log) {
            console.log(str);
        }
        else {
            if($('div#log').length === 0) {
                $('body').append(
                    '<div id="log"></div>');
            }
            $('div#log').html(
                str + '<br/>' + $('div#log').html());
        }
    };
});

/**
 * Add Google tracking to PDF files
 */
$(function() {
    // Files ending with /download or with .pdf
    $('a[href$=/download],a[href$=.pdf],a[href$=.doc],a[href$=.docx],a[href$=.zip]')
        .click(function() {
        if(window.pageTracker && pageTracker._trackPageview) {
            
            fileRegexp =  /^.*?([^\/]+)(?:\/download)?$/;
            anchor = this.toString();
            if(anchor.match(fileRegexp)) {
                fileAlias = anchor.replace(fileRegexp, 
                    '/publications-and-downloads/$1');
                $(this).addClass('tracked');
                pageTracker._trackPageview(fileAlias);
            }
        }
     });
 });

/**
 * link 'terms and conitions' in form help 
 */
 $(function() {
    var linkPattern = /(terms and conditions)/;
    var termsA = $('a[title=Terms]');
    if(termsA.length===1) {
        var href = termsA.attr('href');
        $('p.help').each(function() {
            var html = $(this).html();
            if(html.match(linkPattern)) {
                $(this).html(
                    html.replace(linkPattern, '<a href="'+href+'">$1</a>'));
            }
        });
    }
 });

/**
 * Featured items animation
 */
$(function() {
    
    var FeaturedItem = function(div) {
        
        /*member timer, duration, secondsToNext, config, div, windowDiv,
        slides, firstSlide, windowDims, configuration, selectedN, pageUL,
        titleAnchorPath, imgAnchorPath, descPPath, imgPath, , slidePath,
        paginationClass, getConfig, setUpDom, createSlides, addPagination,
        onPageButtonClick, animateSlide, animateText, initialise, goToSlide,
        onPrevNextClick,
        roll*/
        this.timer = null;
        this.duration = 8;
        this.secondsToNext = this.duration;
        this.config = null;
        this.div = div;
        this.windowDiv = null;
        this.slides = null;
        this.firstSlide = null;
        this.windowDims = {};
        this.configuration = {};
        this.selectedN = 1; // 1 indexed
        this.pageUL = null;
        this.titleAnchorPath = 'div.title-desc h3 a';
        this.imgAnchorPath = '>a';
        this.descPPath = 'div.title-desc p';
        this.imgPath = 'img';
        this.slidePath = 'div.frame>div.inner>div.highlight-frame>*';
        this.paginationClass = 'paging paging-accordion';
    };
    
    FeaturedItem.prototype.initialise = function() {
        this.getConfig();
        this.setUpDom();
        this.createSlides();
        this.addPagination();
        if(this.duration > -1) {
            var fI = this;
            var closure = function() {
                fI.roll();
            };
            this.timer = setInterval(closure,1000);
        }
    };
    
    FeaturedItem.prototype.roll = function() {
        if(this.secondsToNext-- === 0) {
            var next = this.selectedN < this.slides.children().length ?
                this.selectedN+1 : 1;
            this.secondsToNext = this.duration;
            this.goToSlide(next);
        }
    };
    
    FeaturedItem.prototype.getConfig = function() {
        /* Configuration has */
        /*member items, title, link, image, description*/
        
        // The item already on the page
        var domItem = {
            "title":this.div.find(this.titleAnchorPath).text(),
            "link":this.div.find(this.titleAnchorPath).attr('href'),
            "image":this.div.find(this.imgPath).attr('src'),
            "description":this.div.find(this.descPPath).text()
        };
        
        // configuration registered from 'inline' script elements with
        var match = this.div.attr('class').match(
            /featured_item_[a-f0-9]+/);
        if(match) {
            var config = window[match[0]];
            if(config) {                
                config.items.unshift(domItem);
                $.each(config.items, function() {
                    // Remove trailing break tags from description
                    this.description = 
                        this.description.replace(/(?:<br\/>)+$/, '');
                });
                this.config = config;
            }
        }
    };
    
    FeaturedItem.prototype.setUpDom = function() {
        
        this.firstSlide = this.div.find(this.slidePath)
            .wrapAll('<div class="slide"/>').parent();
        this.windowDims = {
            width: this.firstSlide.width(),
            height: this.firstSlide.height()
        };
        this.firstSlide.css(this.windowDims);
        this.slides = this.firstSlide.wrapAll('<div class="slides"/>')
            .parent().css('width', 99999);
        this.windowDiv = this.slides.wrapAll('<div class="window"/>')
            .parent().css(this.windowDims);
    };
    
    FeaturedItem.prototype.createSlides = function() {
        // Duplicate the first slide for each item and populate
        var fI = this;
        var count = 0;
        $.each(this.config.items, function() {
            // Don't create slide for first, it's already on the page
            if(count++ === 0) {
                return true;
            }
            var newSlide = fI.firstSlide.clone();
            newSlide.find(fI.titleAnchorPath).html(this.title);
            newSlide.find(fI.descPPath).html(this.description);
            newSlide.find(fI.imgAnchorPath).attr('href', this.link);
            newSlide.find(fI.titleAnchorPath).attr('href', this.link);
            newSlide.find(fI.imgPath).attr('src', this.image);      
            fI.slides.append(newSlide);
        });
        this.firstSlide.addClass('current-slide');
    };
    
    FeaturedItem.prototype.onPageButtonClick = function(li) {
        this.secondsToNext = this.duration;
        var newN = parseInt($(li).text(), 10);
        this.goToSlide(newN);
    };
        
    FeaturedItem.prototype.goToSlide = function(n) {
        if(n === this.selectedN) {
            return;
        }
        // Change selectedN and button class and slide class
        this.slides.find('>*:nth-child('+this.selectedN+')')
            .removeClass('current-slide');
        this.pageUL.find('>*:nth-child('+this.selectedN+')')
            .removeClass('active');
        this.selectedN = n;
        this.pageUL.find('>*:nth-child('+this.selectedN+')')
            .addClass('active');
        this.slides.find('>*:nth-child('+this.selectedN+')')
            .addClass('current-slide');
        
        this.animateSlide();
    };
    FeaturedItem.prototype.onPrevNextClick = function(span) {
        this.secondsToNext = this.duration;
        if($(span).hasClass('prev')) {
            if(this.selectedN > 1) {
                this.goToSlide(this.selectedN-1);
            }
        }
        else if($(span).hasClass('next')) {
            if(this.selectedN < this.slides.children().length) {
                this.goToSlide(this.selectedN+1);
            }
        }
    };
    
    FeaturedItem.prototype.animateSlide = function() {    
        
        var targetX = 0, i = this.selectedN;
        while(i > 1) {
            var slide = this.slides.find('>*:nth-child(' + (--i) + ')');
            targetX -= slide.width();
        }
        this.slides.animate({left: targetX}, 800);
    };
    
    FeaturedItem.prototype.addPagination = function() {
        if(this.slides.children().length > 1) {
            
            
            var pageDiv = $(
                '<div class="'+ this.paginationClass +  '">' +
                '<span class="prev">prev</span>' +
                '<ul class="js"></ul>' +
                '<span class="next">next</span>'+
                '</div>');
            var footer = this.div.find('div.portletFooter');
            if(footer.length===1) {
                footer.prepend(pageDiv);
            }
            else {
                this.div.find('div.frame').append(pageDiv);
            }
            var fI = this;
            pageDiv.find('>span').click(function() {
                fI.onPrevNextClick(this);
            });
            this.pageUL = pageDiv.find('ul');
            var pageUL = this.pageUL;
            var counter = 1;
            this.slides.children().each(function() {
                var li = $('<li><span>' + counter + '</span></li>');
                if(counter++ === 1) {
                    li.addClass('active');
                }
                pageUL.append(li);
            });
            pageUL.children().click(function() {
                fI.onPageButtonClick(this);
            });
        }
    };
    
    /**
     * Specialisation for min featured items, extends FeaturedItem
     */
    function MiniFeature(div) {
        FeaturedItem.call(this, div);
        this.slidePath = 'div.frame>div.inner>a';
        this.paginationClass = "paging";
        this.duration = -1;
    }
    MiniFeature.prototype = new FeaturedItem();
    
    MiniFeature.prototype.animateSlide = function() {
          
        FeaturedItem.prototype.animateSlide.call(this);
        
        var frame = this.div.find('div.frame');
        var configItem = this.config.items[this.selectedN-1];
        var titleDesc = frame.find('div.title-desc');
        titleDesc.css('position', 'relative');
        var titleDescParent = titleDesc.parent();
        
        // Create an off screen titleDesc for the new copy
        titleDesc.css('width', titleDesc.width());
        var osTitleDesc = titleDesc.clone();
        osTitleDesc.css({position:'absolute',top:'-999px'});
        osTitleDesc.find('h3>a').text(configItem.title);
        osTitleDesc.find('p').text(configItem.description);
        titleDescParent.append(osTitleDesc);
        var delta = osTitleDesc.height() - titleDesc.height();
        osTitleDesc.remove();
        
        var titleDescHeight = titleDesc.height();
        titleDesc.css('height', titleDescHeight);
        var mask = $('<div class="mask"/>');

        var afterUnmask = function() {
            mask.remove();
        };
        var afterGrow = function() {
            mask.css({'height': titleDesc.height(), opacity:1});
            titleDesc.find('h3>a').html(configItem.title).attr('href', configItem.link);
            titleDesc.find('p').html(configItem.description);
            titleDesc.css({height:''});
            mask.animate({opacity:0}, 200, 'swing', afterUnmask);
        };
        var afterMask = function() {
            titleDesc.find('h3>a').html('');
            titleDesc.find('p').html('');
            mask.css({opacity:0,height:1});
            if(Math.abs(delta) > 0) {
                var newHeight = titleDescHeight + delta;
                titleDesc.animate({height:newHeight}, 300, 'swing', 
                    afterGrow);
            }
            else {
                afterGrow();
            }
        };
        
        // Create a mask for smooth text fading across browser
        mask.css({
            width:titleDesc.width(),height:titleDesc.height(),opacity:0});
        titleDesc.append(mask);
        mask.animate({opacity:1}, 200, 'swing', afterMask);
    };

    // Instantiate
    $('div.featured-items').each(function() {
        var fI;
        if($(this).hasClass('conteiner')) {
            fI = new FeaturedItem($(this));
            fI.initialise();
        }
        else if($(this).hasClass('min-conteiner')) {
            fI = new MiniFeature($(this));
            fI.initialise();
        }
    });
    
});





/**
 * Interactive map
 */
function onMapLoaded() {
    
    $('div#content').css('visibility', 'visible');
    window.onunload = GUnload;
    if(!GBrowserIsCompatible() || /.*iPhone.*/.test(navigator.userAgent)) {
        return;
    }
    
    var map_canvas = $('div#content>div.main-text>div.frame>div.inner')
        .prepend('<div id="pe-map"/>').find('div#pe-map');
        
    var map = new GMap2(map_canvas[0]);
    var bounds = new GLatLngBounds();
    //map.setCenter(new GLatLng(52, -2), 7);
    map.setUIToDefault();

    
    var categories = [];
    
    // Category class
    var Category = function(title, first) {
        /*member first, addPlace, category, setIsVisible, toControlItem,
        places*/
        this.first = first;
        this.title = title;
        this.places = [];
        categories.push(this);
    };
    Category.prototype.addPlace = function(place) {
        place.category = this;
        if(!place.category.first) {
            place.marker.hide();
        }
        this.places.push(place);
    };
    Category.prototype.setIsVisible = function(isVisible) {
        var showOrHide = isVisible ? 'show' : 'hide';
        $.each(this.places, function() {
            this.marker[showOrHide]();
        });
    };
    Category.prototype.toControlItem = function() {
        var checked = this.first ? ' checked="checked"' : '';
        var category = this;
        var html = $(
            '<li><label><input type="checkbox"' + checked +'/>' + 
            this.title + '<span></label></span></li>');
        html.find('input:checkbox').click(function(){
            category.setIsVisible($(this).filter(':checked').length===1);
        });
        return html;
    };
    
    // Place class
    var Place = function(html) {
        /*member LINK_REGEX, point*/
        this.html = html;
        this.point = null;
        this.marker = null;
        var place = this;
        
        // Parse anchor to google maps to glean lat lng
        this.html.find('a[href^=http://maps.google.co.uk/?q=]')
        .each(function() {
            var matched = $(this).attr('href').match(place.LINK_REGEX);
            if(matched) {
                place.point = new GLatLng(1*matched[1], 1*matched[2]);
                bounds.extend(place.point);
                place.marker = new GMarker(place.point);
                html = place.html.wrapAll('<div></div>').parent().html();
                // To work around an issue where info windows are too short
                html = '<div style="width:300px;height:' +
                (Math.round(html.length/3.2)) +
                'px;">' + html + '</div>';
                place.marker.bindInfoWindowHtml(html);
                place.overlay = map.addOverlay(place.marker);
            }
        });
    };
    Place.prototype.LINK_REGEX = new RegExp(
        'http:\\/\\/maps\\.google\\.co\\.uk\\/' +
        '\\?q=(-?\\d+(?:\\.\\d+)?),(-?\\d+(?:\\.\\d+)?)');
    
    // Parse HTML and instantiate category and place objects
    var first = true;
    $('div#content>div.main-text>div.frame>div.inner>*')
        .not('div#pe-map')
        .wrapAll('<div id="pe-map-source"/>')
        .filter('h2').each(function() {
            var h2 = $(this);
            var category = new Category(h2.text(), first);
            first = false;
            h2.nextUntil('h2').filter('h3').each(function() {
                var place = new Place($(this).nextUntil('h2,h3').andSelf());
                category.addPlace(place);
            });
    });
    // Centre and zoom the map
    map.setCenter(bounds.getCenter());
    map.setZoom(map.getBoundsZoomLevel(bounds)-1);
    
    // Generate map controls
    var ul = $('div#sidebar').prepend(
        '<div id="map-controls" class="conteiner">' +
        '<div class="frame"><div class="inner"><h2>Display on map</h2>' +
        '<ul></ul></div></div>').find('div#map-controls ul');
    $.each(categories, function() {
        ul.append(this.toControlItem());
    });    
}     


/**
 * Rounded corners for images and some divs
 */
$(function() {
    
    var wrapCorners = function(el, name) {
        name = name ? name : 'span';
        return el.wrap('<'+name+' class="img-wrap"/>')
            .closest(name+'.img-wrap')
            .prepend(
                '<span class="tr"/><span class="br"/><span class="bl"/>');
    };
    // Wrap highlights and featured links
    wrapCorners($(
         'div.window'), 'div');
    
    // Wrap various images, mirror margin and floats
    $('div#content>div.main-text>div.frame>div.inner>p>img:not([class~=img-grid]),' +
        'div.conteiner>div.frame>div.inner>a>img,')
    .each(function() {
        var img = $(this);
        img.css('display','block');
        var wrap = wrapCorners(img);
        // Properties to copy onto wrapper, and their null values for img
        var props = {
            'margin-top': 0,
            'margin-right': 0,
            'margin-bottom': 0,
            'margin-left': 0,
            'float': 'none'
        };
        for(var prop in props) {
            if(props.hasOwnProperty(prop)) {
                wrap.css(prop, img.css(prop));
                img.css(prop, props[prop]);
            }
        }
    });
});
// Interactive map
/*member loadmap, load, setOnLoadCallback*/
if(window.loadmap) {
    google.load("maps", "2");
    google.setOnLoadCallback(onMapLoaded);
}

$(function() {
    $('body.interactive-map').each(function() {
        if(window.loadmap) {
            // Hide to avoid flicker, show after maps have loaded
            $('div#content').css('visibility', 'hidden');
        }
    });
});




/**
 * Replace form submit buttons with an anchor with click handler
 */
$(function() {
    $('input:submit').each(function() {
        var inpt = $(this);
        //inpt.addClass('none') // Can't do this because of ie7, fork?
        inpt.css('display', 'none')
            .after('<a href="#" class="submit">' + inpt.attr('value') + 
                '</a>').next()
                .click(function() {
                    $(this).closest('form').submit();
                    return false;
                });
    });
});


/**
 * Populate field values from labels, add handlers and hide labels
 */
$(function() {
	$('form.signup input:text')
		.each(function() {
			var input = $(this);
			var label = input.parents('form:first').find(
			    'label[for=' + input.attr('id') + ']');
			var wipeField = function() {
				if(input.val() === label.text()) {
					input.val('');
				}
			};
			var populateField = function() {
				if(input.val() === '') {
					input.val(label.text());
				}
			};
			input.focus(wipeField);
			input.blur(populateField);
			label.hide();
			populateField();
		});
});
