

var avg = 28;
var med = 28;
var min = 26;
var max = 30;
var dev = 2;

var duration = 3;

var known = known || [];
var firsts = [];

/* storage abstraction */
var storage = {
    save_date: function(date) {
        $.post('.save_date', {date: date.toString("yyyy-M-d")})
    },
    remove_date: function(date) {
        $.post('.remove_date', {date: date.toString("yyyy-M-d")})
    }
}

function update_stats() {
	
	cycles = [];
	firsts = [];

    if (known.length > 0) {

	    known.sort(function(d1,d2){return d1.compareTo(d2)});
        var last = known[0];
        firsts.push(last);
	    
        var day_in_millis = 1000*60*60*24;
        var sum = 0;
        avg = 0;
        
	    for (var i=1; i<known.length; i++) {
	        var diff = Math.round((known[i]-last) / day_in_millis);
	        if (diff > 15) {  // ignore following days and afterbleeding
	            cycles.push(diff);
	            sum += diff;
	            last = known[i];
	            firsts.push(last);
	        }
	    }
		
		if (cycles.length < 1) {
	        min = 28;
            max = 28;
            med = 28;
            avg = 28;
	        dev = 2;
		}
		else {
			// sort cycles to find the median
			cycles.sort();
			
			min = cycles[0];
			max = cycles[cycles.length - 1];
            avg = sum / cycles.length;
			
			if (cycles.length % 2 == 0) {
			    med = (cycles[cycles.length / 2 - 1] + cycles[cycles.length / 2]) / 2;
	        }
	        else {
			    med = cycles[(cycles.length - 1) / 2];
	        }
	        
			if (cycles.length > 1) {
				var v = 0;
				for (var i=0; i<cycles.length; i++) {
					v += (avg - cycles[i]) * (avg - cycles[i]);
				}
				v /= cycles.length
				dev = Math.sqrt(v);
			} 
			else {
				dev = 2;
			}
		}
    }
    
	$('.stat-num .value').html(cycles.length);
	showStat('.stat-med', cycles.length > 0 ? (med == Math.round(med) ? med : (Math.round(med) - 1) + ' or ' + Math.round(med)) : ('26-30'));
	showStat('.stat-min', (min != med || max != med) ? min : null);
	showStat('.stat-max', (min != med || max != med) ? max : null);
	
	updateUI();
}

function showStat(selector, value) {
	if (value) {
	    $(selector + ' .value').html(value);
	    $(selector).show();
	}
	else {
	    $(selector).hide();
	}
}

function updateUI() {
	//$('.state-ui').attr('class','state-ui').addClass('num-' + firsts.length);
    
    if (known.length == 0) {
        $('.registerbutton').hide();
        $('.cycle-info').hide();
        $('.num-sel-0').show();
        $('.num-sel-1').hide();
        $('.future-wrapper').addClass('disabled');
    }
    else {
    	$('.future-wrapper').removeClass('disabled');
        $('.num-sel-0').hide();
        $('.registerbutton').show();
        $('.cycle-info').show();
        
    	if (firsts.length == 1) {
	        $('.num-sel-1').show();
    	}
    	else {
    		$('.num-sel-1').hide();
    	}
    }
}

function render() {
	
    $('.calendar .maybe').removeClass('maybe');
    $('.calendar .blood').removeClass('blood');
    $('.calendar .fruit').removeClass('fruit');
	
	if (known.length > 0) {
		
		for (var i=0; i<known.length; i++) {
            $('.d-' + known[i].toString("yyyy-MM-dd")).addClass('blood');			
		}

        var last = firsts[firsts.length - 1];
        
		if (cycles.length > 0 && avg > 25 && avg < 31) {
			var fruit = last.clone().addDays(7);
			for (var i=0; i<12; i++) {
				var $el = $('.d-' + fruit.toString("yyyy-MM-dd"));
                $el.addClass('fruit');
                add_title($el, STRINGS['fruit_str']);
				fruit.addDays(1);
			}
		}		
        
        try {
            var predict_cycles = avg/dev/4; // 2*dev gives period of dev (dev is above *and* below avg), *2 to have reasonably "sharp" prediction
            if (predict_cycles < 1) predict_cycles = 1;
            if (predict_cycles > 10) predict_cycles = 10;
        }
        catch (zeroDiv) {
            var predict_cycles = 10;
        }

        for (var i=1; i <= predict_cycles; i++) {
    	    var next = last.clone().addDays(Math.round((avg - dev) * i));
    	    var end = last.clone().addDays(Math.round((avg + dev) * i) + duration);
    	    
    	    while (next.compareTo(end) < 0) {
    	        var $el = $('.d-' + next.toString("yyyy-MM-dd"));
    	        // is this day displayed at all?
    	        if ($el.length > 0) {
        	        $el.addClass('maybe');
                    add_title($el, STRINGS['strawberry_str']);
        	    }
        	    next.addDays(1);
    	    }
        }
    }
}

function add_title($el, new_title) {
    var title = $el.attr('title');
    var idx = title.indexOf('|');
    if (idx > -1) {
        title = $.trim(title.substring(0,idx));
    }
    if (title != '') title += ' | ';
    title += new_title;
    $el.attr('title', title);
}

function index_of_date(date) {
	for (var i=0; i<known.length; i++) {
		if (known[i] - date == 0) return i;
	}
	return -1;
}


function showPage(selector){
	
	$page = $(selector);
	
	// Collapse the keyboard
	$(':focus').blur();
	
	$('.current').removeClass('current');
	$page.addClass('current');

    $('.pager.active').removeClass('active');
    $('.pagerpanel').find('a[href=' + selector + ']').addClass('active');
    	
	return false;	
}

function pad(num, num_digits) {
    var str = '' + num;
    while (str.length < num_digits) {
        str = '0' + str;
    }
    return str;
}

$(document).ready(function(){

    var now = new Date();
    var day_id = now.getFullYear() + '-' + pad(now.getMonth() + 1, 2) + '-' + pad(now.getDate(), 2);
    var $today = $('.d-' + day_id);
    $today.addClass('today');
    $today.append('<div class="l-today">' + STRINGS['today_str'] + '</div>');
    
	
	updateUI();
	
	$('.past .day').click(function(event) {
		
        /*
		var title = this.title;
		var idx = title.indexOf('|');
		if (idx > -1) title = title.substring(0,idx);
		
	    var date = Date.parse(title);
        */

        var date = null;
        var classes = this.className.split(' ')
        for (var i=0; i<classes.length; i++) {
            if (classes[i].indexOf('d-') == 0) {
                date = classes[i].split('-');
                // always include radix for javascript's parseInt! http://stackoverflow.com/questions/850341/workarounds-for-javascript-parseint-octal-bug
                date = new Date(parseInt(date[1],10),parseInt(date[2],10)-1,parseInt(date[3],10))
                break;
            }
        }

        if (!date) return;

	    var pos = index_of_date(date);
	    
	    if (pos == -1) {
            known.push(date);
            storage.save_date(date);
            $(this).addClass('blood');
            track('calendar', 'add_date');
	    }
	    else {
            known.splice(pos,1);
            storage.remove_date(date);
            $(this).removeClass('blood');
            track('calendar', 'remove_date')
	    }
	    window.setTimeout(function(){
	        update_stats();
	        render();
            if (known.length == 1) {
                // show prediction on first click on phone
                showPage('#prediction');
            }
	    }, 500)
	});
	
    $('.show-earlier').click(function(ev){
        $('.show-earlier').hide();
        $('.recent .startlabel').hide();
        $('.hide-earlier').show();
        $('.earlier').show();
        setTimeout(function(){
        	$(window).scrollTop($(window).scrollTop() + 600);
        }, 200);
        ev.preventDefault();
    });
    $('.hide-earlier').click(function(ev){
        $('.earlier').hide();
        $('.show-earlier').show();
        $('.recent .startlabel').show();
        $('.hide-earlier').hide();
        ev.preventDefault();
    });
    /*
    $('.save-form input').focus(function(ev){
        var el = this;
        window.setTimeout(function() {
        	$(el).parents('.extra-wrapper').addClass('expanded');
            el.focus();
        }, 100);
    });*/
    /*
    $('.save-form h4 span').click(function(ev){
    	$f = $(this).parents('.extra-wrapper').toggleClass('expanded');
        $('.getstarted').hide();
    });
    $('.hide-extra').click(function(ev){
        $(this).parents('.extra-wrapper').removeClass('expanded');
        ev.preventDefault();
    });
    $('.save-form .hide-extra').click(function(ev){
        $(this).parents('form').find('input.text').val('');
        ev.preventDefault();
    });
    */
    $('.hideregister').click(function(ev){
        $('.save-form').hide();
        $('.registerbutton').show();
    });
    $('.showregister').click(function(ev){
        $('.save-form').show();
        $('.registerbutton').hide();
        $('.getstarted').hide();
        track_pageview('/.registration/');
    });
    
    $('.showsettings').click(function(ev){
        var settings = $('#settings');
        var was_visible = settings.is(':visible');
        settings.slideToggle();
        if (!was_visible) {
            window.setTimeout(function(){track_pageview('/.settings/')}, 500);
        }
    });
    $('.showshare').click(function(ev){
        var $share = $('#share');
        var was_visible = $share.is(':visible');
        $share.slideToggle();
        if (!was_visible) {
            window.setTimeout(function(){track_pageview('/.share/')}, 500);
        }
    });
    
    $('#settings-form button[type="submit"]').click(function(ev) {
        var $form = $('#settings-form');
        $form.addClass('submitting');
        $form.removeClass('ok');
        var data = $form.serialize();
        $.post($form.attr('action'), data, function() {
           // success
            $form.removeClass('submitting');
            $form.addClass('ok');
            //$('#settings').slideUp();
            window.setTimeout(function(){$('#settings').slideUp()}, 500);
        });
        ev.preventDefault();
    });
    $('#settings-form input').change(function(ev) {
        $('#settings-form').removeClass('ok');
    });
    
	var timer = null;
	$('input.calendar-name').keyup(function(ev){
		
		var $el = $(this),
		    name = $el.val();
		    
        if (timer) {
        	window.clearTimeout(timer);
        	timer = null;
        }
        if (name.length > 0) {
			timer = window.setTimeout(function() {
				var $help = $('#name-help');
				var $label = $('#name-help-label');
                $label.html('Checking name...');
                $help.removeClass('error valid')
                $help.addClass('waiting');
	            $.getJSON('.check_name/' + name + '/', function(data){            	
	                if (data.type=='error') {
	                	$label.html(data.message);
                        $help.removeClass('waiting valid');
                        $help.addClass('error');
	                }
	                else {
                        $label.html(data.message);
                        $help.removeClass('waiting error');
                        $help.addClass('valid');
	                }
	            })			
			}, 1000);
        }
        else {
            var $help = $('#name-help');
            var $label = $('#name-help-label');
            $help.removeClass('waiting error valid')
        	$label.html('Letters, numbers and<br />_ or - allowed');
        }
	});
    $('.pager').click(function(ev) {
	    var $el = $(ev.target);
	    if ($el.attr('nodeName')!=='A'){
	        $el = $el.parent('a');
	    }
	    
	    var target = $el.attr('target'), 
	        hash = $el.attr('hash'); 
	    
	    if ($el.attr('target') == '_blank' || $el.attr('rel') == 'external') {
	        return true;
	    }
	    
	    if (hash && hash != '#') {
	
	        showPage(hash);
	        
            ev.preventDefault();
            return false;
	    }
	    
    });
    
    $('.getstarted .closebtn').click(function(ev){
    	$(this).parent().hide();
    });
    $('.panel .closebtn').click(function(ev){
    	$(this).parent().slideUp();
    });
    $('.logout-action').click(function(ev){
       $('#logout-form')[0].submit(); 
    });
    
    window.setTimeout(function(){
        update_stats();
        render();
    }, 500)
	
});

if (navigator.userAgent.indexOf('iPhone') != -1) {
    addEventListener("load", function() {
        setTimeout(function(){window.scrollTo(0, 0)}, 0);
    }, false);
}



