
var trainer = function () {

    var trainingSessionId;
	var wordsById;
	
	var currentTrainingList;//list of word ids
	var nextTrainingList;
	
    var wrongCount;
    var currentWordId;
    var showingPrompt;
    var speed = 1000;
    var prevWrongGuess;
    
    var stats;//shown at the end of the training session

    function init(id, words) {
        trainingSessionId = id;
		stats = {
			'trainingSessionId': id,
			'startTime': (new Date()).getTime(), 
			'endTime': null,
			'wordsById': []
		};
		
		wordsById = {};
		currentTrainingList = [];
		for(var i = 0; i < words.length; i++) {
			stats.wordsById[words[i]['id']] = {'word': words[i]['word'], 'timesRight':0, 'timesWrong':0};
			wordsById[words[i]['id']] = words[i]['word'];
			currentTrainingList.push(words[i]['id']);
		}
		
        nextTrainingList = [];
        showingPrompt = false;
		prevWrongGuess = null;
        
		//unbind anything that was setup from a previous session
        $('#input').unbind('keypress', input_keydown);
        $('#checkword').unbind('click', submitGuess);
		$('#skipword').unbind('click', skipWordClick);
		$('#reprompt').unbind('click', repromptClick);
		//rebind
        $('#input').bind('keypress', input_keydown);
        $('#checkword').bind('click', submitGuess);
		$('#skipword').bind('click', skipWordClick);
		$('#reprompt').bind('click', repromptClick);
		
		$('#input').focus();
        nextWord();
    }
    
    function nextWord() {
		//if we have more words in this round
        if(currentTrainingList.length > 0) {
			//get and remove one of the ids from the current list
            currentWordId = currentTrainingList.splice(Math.floor(Math.random() * currentTrainingList.length), 1)[0];
            wrongCount = 0;
            showPrompt();
        } else { //done with this round
			//do we have words to repeat?
			for(var i = 0; i < nextTrainingList.length; i++) {
                currentTrainingList.push(nextTrainingList[i]);
			}
            nextTrainingList = [];
            if(currentTrainingList.length > 0) {
                //$('#tryagain').show();
                $('#prompt').html("Let's try some of those again.");
                var promptColor = $('#prompt').css("color");
                $('#prompt').css("color", "#aaa");
                $('#input').attr("disabled", true); 
                setTimeout(function () {
                    //$('#tryagain').hide();
                    $('#prompt').html("");
                	$('#prompt').css("color", promptColor);
                    $('#input').removeAttr("disabled"); 
                    $('#input').focus(); 
                    //showPrompt();
					nextWord();
                }, 1500);
            } else {
                //incScore(10);
                stats.endTime = (new Date()).getTime();
                endTrainingSession(stats);
            }
        }
    }
    
    function showPrompt() {
		var currentWord = wordsById[currentWordId];
		showingPrompt = true;
		
		if(!prevWrongGuess) { // null or empty string
			$('#prompt').html(currentWord);
		} else {
			$('#prompt').html(getDiff(currentWord, prevWrongGuess));
			$('.diff_rem').delay(1000).animate(
				{'font-size':0},
				1000,
				function() { $(this).hide(); }
			);
		}
		
		var t = speed * Math.log(currentWord.length) * Math.pow(1.5, wrongCount);
		t = (t > 5000) ? 5000 : t;// TODO: move magic numbers elsewhere
		
		var timeId = (new Date()).getTime();
		$('#prompt').data('timeId', timeId);
		//setTimeout(function() {
		//	//match stored against closure value (timeId)
		//	if ($('#prompt').data('timeId') == timeId) {
		//		hidePrompt();
		//	}
		//}, t);
    }
	
    function hidePrompt() {
        $('#prompt').html('&nbsp;');
        showingPrompt = false;
        $('#input').css('backgroundColor', '#fff');
    }
    
    function input_keydown(e) {
		if (e.keyCode == 13 || e.keyCode == 10) {
			if($('#input').val() != "") {
				submitGuess();
			}
		} else if (showingPrompt) {
			showingPrompt = false;
			hidePrompt();
		}
    }
	
	function submitGuess() {
		var guess = $('#input').val();
		guess = jQuery.trim(guess);
		guess = guess.toLowerCase();
		if(guess == wordsById[currentWordId].toLowerCase()) {
			prevWrongGuess = null;
			stats.wordsById[currentWordId].timesRight += 1;
			logTrainingResult(trainingSessionId, currentWordId, true);
			incScore(1);
			nextWord();
		} else { //got it wrong
			prevWrongGuess = $('#input').val();
			stats.wordsById[currentWordId].timesWrong += 1;
			logTrainingResult(trainingSessionId, currentWordId, false, prevWrongGuess);
			wrongCount += 1;
			if(wrongCount === 1) {
				nextTrainingList.push(currentWordId);
			}
			//this is really reshowPrompt()
			showPrompt();
		}
		$('#input').val('');
	}
	
	function skipWordClick(e) {
		prevWrongGuess = null;
        logTrainingResult(trainingSessionId, currentWordId, false, "");//TODO: included skipped?
		var index = nextTrainingList.indexOf(currentWordId);
		if(index != -1)
			nextTrainingList.splice(index, 1);
        nextWord();
		$('#input').focus(); 
	}
	
	function repromptClick(e) {
		$('#input').val('');		
		if(wrongCount == 0) {
			wrongCount += 1;
		}
		if(wrongCount === 1) {
			nextTrainingList.push(currentWordId);
		}
		showPrompt();
		$('#input').focus();
	}

	//expose public API
    return {
        'init':init
    };
}();