(function($) {
//Polling functionality

$.mmsGenericPoll = {
    speed: 1000, //The speed at which transitions happen
    baseCookieDomain: '', //Domain to use for cookies
    services: { poll: '', answer: '' }
};


//Templates for generating pieces of the poll
$.mmsGenericPoll.templates = {
    poll: '<div id="genericPoll1" class="genericPoll genericPollOpen">' + 
        '<h2><span>Physician\'s First Watch Poll</span></h2>' +
		'<div class="content"><h3>Questions</h3><p class="vote"><span>Vote</span></p>' +
        '<p class="thanks">Thank you for voting!</p><p class="status"></p>' +
        '<p class="responses">(<span class="totalVotes"></span> total responses)</p></div></div>',                

    question: '<div class="question"><p></p><ul></ul></div>',

    answer: '<li><input name="aName" id="anId" type="radio"></input><label></label>' +
        '<div class="resultBar"><div class="bar"></div>' + 
        '<div class="pct"></div></div></li>'
};


//Regular expressions used in the polling app
$.mmsGenericPoll.regex = {    
    //Matches pollAnswer query param value
    pollVote: /pollVote=(\d+)/i
};


//Show a single poll based on a service call
$.mmsGenericPoll.singlePoll = function(id, settings) {
    $.extend($.mmsGenericPoll, settings);
    $.ajax({ dataType: 'jsonp', url: $.mmsGenericPoll.services.poll + '?id=' + id,
        success: function(data) { $.mmsGenericPoll.processPollData(data); }});
};

//Show a single poll based on a service call
$.mmsGenericPoll.singlePollByName = function(name, settings) {
    $.extend($.mmsGenericPoll, settings);
    $.ajax({ dataType: 'jsonp', url: $.mmsGenericPoll.services.poll + '?name=' + name,
        success: function(data) { $.mmsGenericPoll.processPollData(data); }});
};


//Process poll data and create the poll
$.mmsGenericPoll.processPollData = function(data) {
    if(data.questions) {
	    var poll = $($.mmsGenericPoll.templates.poll); //Make the poll from its template
	    poll.data = data;
	    
	    //Fill in the title with the name of the poll
	    poll.find('h2 span').text('');
    	
	    //Add each poll question to the poll
        $.each(data.questions, 
            function(i) { $.mmsGenericPoll.buildQuestion(i, this, poll); });
            
        //poll.find('.question:last').addClass('last');
        
        $('#genericPoll').replaceWith(poll); //Add the poll to the DOM
        
        //Determine if this poll is open, answered, and which date to display
        //in the status (i.e. 'Poll opened x/y/z')
        var open = !data.closeDate || $.mmsJsonDate(data.closeDate) > new Date(),
            answered = $.cookie('genericPoll' + poll.data.id) == 'voted',
            date = $.mmsJsonDate(open ? data.openDate : data.closeDate);
          
        $.mmsGenericPoll.displayPoll(poll, open, answered, date); //Display the poll
        
        //If a pollVote query parameter is specified, vote for that option
        window.location.href.replace($.mmsGenericPoll.regex.pollVote, function(m, id) {
            poll.find('input:eq(' + id + ')').attr('checked', 'checked').end()
                .find('.vote').trigger('click', poll).end();
        });
	}
};


//Display a poll according to its state
$.mmsGenericPoll.displayPoll = function(poll, open, answered, date) {
    //Build up the poll status string
    var formattedDate = $.dateFormat(date, 'mmm. d, yyyy'),
        status = 'Poll ' + (open ? 'Opened ' : 'Closed ') + formattedDate;
    poll.find('.status').text(status).end();
     
    //Don't display thanks for voting once the poll is closed
    if(!open) poll.find('.thanks').remove().end();
    
    //Set up a new user link
    if(open)
        poll.find('.newUser').click(function() { 
			ntptEventTag('ev=pollNewUser');         
            $.cookie('genericPoll' + poll.data.id, null, 
                { domain: $.mmsGenericPoll.baseCookieDomain });
            $('#genericPoll1').replaceWith('<div id="genericPoll"></div>');
            $.mmsGenericPoll.processPollData(poll.data);
        });
    else
        poll.remove('.newUser');
    
    //The poll is open and unanswered
    if(open && !answered) {
        poll.find('.thanks, .responses, .resultBar, .newUser').hide().end()
            .find('.vote').bind('click', poll, $.mmsGenericPoll.vote).end();
    }
    //The poll is either closed or answered
    else {
        poll.find('.vote').hide().end()
            .find('input').attr('disabled', 'disabled').end();
     
        $.mmsGenericPoll.showResults(poll);
    }
};


//Build a poll question and it's answers out of its template
$.mmsGenericPoll.buildQuestion = function(qIndex, question, poll) {
    var el = $($.mmsGenericPoll.templates.question), 
        ul = el.find('ul'),
        name = 'genericPoll1q' + qIndex;
    
    //Add answers to this question
    $.each(question.answers, 
        function(i) { ul.append($.mmsGenericPoll.buildAnswers(name, i, this)); });

    //Add each question right before the vote button
	poll.find('.vote').before(el.find('p').text(question.question).end());
};


//Create each answer out of its template
$.mmsGenericPoll.buildAnswers = function(name, aIndex, answer) {
    var id = name + 'a' + aIndex;

    //Modify the template to fill it in and make the label match the input
    return $($.mmsGenericPoll.templates.answer.replace('aName', name))
        .find('input').attr('id', id).end()
        .find('label').text(answer.text).attr('for', id).end();
};


//Handle a click of the vote button
$.mmsGenericPoll.vote = function(e) {
    var questions = e.data.find('.question');
    //Get a mapping of questions answered to answers selected
    var votes = $.mmsGenericPoll.mapVotes(e.data.find('input:checked'));
    
    //Register the vote if all question have been answered
    if($.mmsPropertyCount(votes) == questions.length) 
        $.mmsGenericPoll.registerVote(e.data, votes);
    else
        $.mmsGenericPoll.alertUnanswered(questions, votes);
};


//Alert the user that they haven't answered all questions
$.mmsGenericPoll.alertUnanswered = function(questions, votes) {
    questions.each(function(i) {
        if(!votes[i])
            $(this).css('background-color', '#fdfd80').animate({'backgroundColor': '#ffffff'}, $.mmsGenericPoll.speed);
    });
};


//Register the vote and show results
$.mmsGenericPoll.registerVote = function(poll, votes) {
	//add submitpoll event tag
	ntptEventTag('ev=submitPoll');	
    //Write a cookie to indicate that this poll has been answered
    $.cookie('genericPoll' + poll.data.id, 'voted', 
        {domain: $.mmsGenericPoll.baseCookieDomain, expires: 365});

    //Build up the answer URL
    var params = 'id=' + poll.data.id, q = poll.data.questions;
    for(x in votes) params += '&q' + q[x].id + '=' + q[x].answers[votes[x]].id;
    
    //Register the answers
    $.mmsGenericPoll.sendVote($.mmsGenericPoll.services.answer + '?' + params);

    //Add the votes to the existing vote counts. We do this rather than getting
    //new vote counts from the server since it allows for immediate feedback
    $.mmsGenericPoll.eachAnswer(poll, function(i, j) { votes[i] == j && this.votes++; });
    
    //Disable the radio buttons, hide the vote button, and show results
    poll.find('input').attr('disabled', 'disabled').end()
        .find('.vote').mmsFadeHide($.mmsGenericPoll.speed / 2,
            function() { $.showResultsDelayed(poll); });
};


//Send the vote (separate function so it can be disabled)
$.mmsGenericPoll.sendVote = function(url) { $.ajax({dataType: 'jsonp', url: url}); };


//Create an object whose keys and values match up with the selected options.
$.mmsGenericPoll.mapVotes = function(selectedOptions) {
    var votes = {};
    selectedOptions.each(function() {
        //IDs are formatted like 'genericPoll1q1a3'
        var vote = this.id.match(/q(\d*)a(\d*)$/);
        //Turn them into key: value, e.g. { 1: 3 }
        votes[new Number(vote[1])] = new Number(vote[2]);
    });
    
    return votes;
};


//Show the results after a delay
$.showResultsDelayed = function(poll) {
    setTimeout(function() { $.mmsGenericPoll.showResults(poll); }, $.mmsGenericPoll.speed / 2);
};


//Show results - bars, percentages, etc
$.mmsGenericPoll.showResults = function(poll) {
    //Find the inital width of the bars
	var bars = poll.find('.bar');
	poll.find('.resultBar').show();
	var startWidth = bars.width();
	poll.find('.resultBar').hide();

    //Get the total # of votes by summing the votes to the first question
	var totalVotes = 0, q = poll.data.questions[0];
	$.each(q.answers, function() { totalVotes += new Number(this.votes); });

	//Find the final width of each bar
	$.mmsGenericPoll.calcResults(poll, totalVotes, startWidth);
	poll.find('.totalVotes').text(totalVotes);
    
	//Start the bars at 0 pixels and fade them in
	bars.width(0);
	poll.find('.resultBar').mmsFadeShow($.mmsGenericPoll.speed).end()
	    .find('.pct').add(bars).fadeIn($.mmsGenericPoll.speed);
	
	//Animate each bar to its full width 
	bars.each(function(i) {
	    $(this).animate({width: $(this).attr('barWidth')}, $.mmsGenericPoll.speed); });
	
	//Show thanks and # of responses
	poll.find('.thanks, .responses').mmsFadeShow($.mmsGenericPoll.speed);
};


//Calculate bar widths and percentages
$.mmsGenericPoll.calcResults = function(poll, totalVotes, startWidth) {
	var bars = poll.find('.bar'), pcts = poll.find('.pct');
	
	//Loop through each answer
	var i = 0;
	$.mmsGenericPoll.eachAnswer(poll, function() {
        //Calculate the width of each bar and it's percentage
        var ratio, width = 1, pct = 0;
        if(totalVotes > 0) {
            ratio = this.votes / totalVotes;
            width = Math.max(Math.round(ratio * startWidth), 1);
            pct = Math.round(ratio * 100);
        }
        
        //Set custom attributes and the percentage text
        bars.eq(i).attr('barWidth', width).attr('votePct', pct);
        pcts.eq(i).text(pct + '%');
	    i++;
    });
};


//Loop through each answer in each question
$.mmsGenericPoll.eachAnswer = function(poll, fn) {
    $.each(poll.data.questions, function(i) {
        $.each(this.answers, function(j) { fn.apply(this, [i, j]); }); 
    });
};


})(jQuery);