var LoadData = function(callback) {
    var instance = this;
    
    // set callback to call after loading is done
    instance.callback = callback;
    
    instance.load();
}

LoadData.prototype.load = function() {
    var instance = this;
    
    $.ajax({
        url: 'js/data.json',
        dataType: 'json',
        success: function() { instance.onSuccess.apply(instance, arguments) },
        error: function() { instance.onError.apply(instance, arguments) },
        complete: function() { instance.onComplete.apply(instance, arguments) }
    });
}

LoadData.prototype.onSuccess = function(data, textStatus, XMLHttpRequest) {
    var instance = this;
    
    instance.data = data;
    
    instance.callback(data);
}

LoadData.prototype.onError = function(XMLHttpRequest, textStatus, errorThrown) {
    var instance = this;
}

LoadData.prototype.onComplete = function(XMLHttpRequest, textStatus) {
    var instance = this;
}

var Word = function(object) {
    var instance = this;
    
    instance.id = object.id;
    instance.label = object.label;
    instance.cat_id = object.cat_id;
    instance.time = -1;
    instance.colorClass = '';
}

var Handels = function() {
	var instance = this;
};

Handels.prototype.ready = function(data) {
    var instance = this;
    
    // setting some basic variables
    instance.steps = data.steps;
	instance.data = data;
	instance.activeCategory = {left: [], right: []};
	instance.activeWords = [];

    // init's the game
	instance.init();
    
    // sets up some events
    $('form#user-data').change(function() { instance.formHandler.apply(instance, arguments) });
    
    $('.detailed-results-button').click(function() {
        $('#post-game').hide();
        $('#detailed-results').show().fadeIn('fast');
        return false;
    });
    
    $('#starta-testet').click(function() {
        instance.startGame.apply(instance, arguments);
    });
    
    $('.om-testet').click(function() {
        $('#detailed-results').hide();
        instance.activeWindow = instance.returnWindow;
        instance.windowHandler($('#about-game'));
        return false;
    });
    
    $('.close').click(function() {
        $('#detailed-results').hide();
        instance.windowHandler(instance.returnWindow);
    });
};

Handels.prototype.init = function() {
	var instance = this;
    
    instance.userData = {};
    instance.step = 0;
    instance.activeWindow = null;
    instance.returnWindow = $('#pre-game');
};

Handels.prototype.reset = function() {
	var instance = this;
    
    // reseting of variables between game steps
    instance.i = 0;
    instance.wordPos = 0;
    instance.correctAnswers = 0;
    instance.isStarted = false;
    instance.wordStarted = 0;
    instance.wordStopped = 0;
    instance.stepStarted = 0;
    instance.stepEnded = 0;
    //instance.showedInfo = false;
    instance.activeWords = [];
	instance.activeCategory = {left: [], right: []};
	instance.triggeredSide = '';
};

Handels.prototype.prepare = function() {
    var instance = this;
    
    $('.between').hide();
    $('.bottom').hide();
    
    var currentStep = instance.steps[instance.step];
    
    // loops the categories found in the current step
	for (var i=0; i < currentStep.categories.length; i++) {
		var label = currentStep.categories[i].label;
		var align = currentStep.categories[i].align;
		var order = currentStep.categories[i].order;
		var colorClass = currentStep.categories[i].colorClass;
		
		// sets how many times each word should be repeated
		var occurance = 2;
        
        var category = instance.data.categories[label];
        
        // positions the categories in the right side of the screen
        var position = '';
        
        switch(align) {
            case 'left':
                position = '.left .'+order;
                instance.activeCategory.left.push(category.id);
            break;
            
            case 'right':
                position = '.right .'+order;
                instance.activeCategory.right.push(category.id);
            break;
        }

        if(order == 'bottom') {
            $('.between').show();
            $('.bottom').show();
        }
        
        // adds prefix for words in the bottom
        //label = order == 'bottom' ? 'eller '+label : label;
        // sets the correct color class
        $(position).text(label).removeClass('white green').addClass(colorClass);
        
        // creates new words and puts them in the activeWords array
		for (var j=0; j < occurance; j++) {
			for (var k=0; k < category.words.length; k++) {
			    var w = new Word(category.words[k]);
			    w.colorClass = currentStep.categories[i].colorClass;
				instance.activeWords.push(w);
			};
		};
	};
    // shuffles the order of the array
	instance.activeWords = instance.activeWords.sort(function() {return 0.5 - Math.random()});
};

Handels.prototype.updateStepInfo = function(object) {
    // updates the information text found between each step
    $("#step-info .step h2").html(object.header);
    $("#step-info .instructions").html(object.instructions);
    $("#step-info .additional").html(object.additional);
};

Handels.prototype.startGame = function() {
    var instance = this;
    
    // checks that we still have steps left to run
    if(instance.step < instance.steps.length) {
        // checks if we have a current game ongoing
        if(!instance.isStarted) {
            if(!instance.showedInfo) {
                instance.showedInfo = true;
                
                instance.updateStepInfo(instance.steps[instance.step].message);
                
                $('#step-info').fadeIn('fast', function() {
                    instance.reset();
                    instance.prepare();
                    instance.findNextWord(false);
                    
                    $('#game-box').show();
                });
                
                

                
            } else {
                instance.isStarted = true;
                instance.stepStarted = new Date().getTime();
                $('#step-info').fadeOut('fast');
                
            }
        }
    } else {
        // if all steps are completed we'll summarize
        $('#game-box').fadeOut('fast', function() { instance.finalSummary.apply(instance, arguments) });
    }
}

Handels.prototype.findNextWord = function(fadeInWord) {
    var instance = this;
    
    // loops until it finds an unanswered word or till all words are correct
    while(instance.correctAnswers < instance.activeWords.length) {
        if(instance.activeWords[instance.i].time < 0) {
            instance.wordPos = instance.i;
            var w = instance.activeWords[instance.wordPos];
            
            $('#word').text(w.label).removeClass('white green').addClass(w.colorClass).stop().fadeTo(0, .4).fadeTo((fadeInWord != false ? 400 : 0), 1);
            
            instance.wordStarted = new Date().getTime();
            
            instance.i = (instance.i+1)%instance.activeWords.length;
            
            return;
        }
        
        instance.i = (instance.i+1)%instance.activeWords.length;
    }
}

Handels.prototype.windowHandler = function(elem, callback) {
    var instance = this;
    
    // handler for fading the current box/window to a new one
    if(!instance.activeWindow) {
        elem.fadeIn('fast');
        instance.activeWindow = elem;
    } else {
        instance.activeWindow.fadeOut('fast', function() {
            instance.activeWindow = elem;
            if(callback) callback();
            elem.fadeIn('fast');
        });
    }
};

Handels.prototype.onKey = function(e) {
    var instance = this;
    var code = e.which;
    
	switch(code) {
	    case 32: // space
    	    instance.startGame();
		break;
		
		case 69: // e
            instance.triggeredSide = 'left';
            instance.processWord();
        break;
        
        case 73: // i
            instance.triggeredSide = 'right';
            instance.processWord();
        break;
	}
}

Handels.prototype.formHandler = function(e) {
    var instance = this;
    
    // checks if all options have been selected in the form
    
    instance.formElements = {};
    instance.userData[e.target.name] = e.target.value;
    
    // not very DRY; it will eventually find out if the checked number of form elements matches the total... 
    $("form#user-data input:checked").each(function() { instance.countElements.apply(instance, arguments) });
    
    var count = 0;
    for (var key in instance.formElements) count++;
    
    $("form#user-data input").each(function() { instance.countElements.apply(instance, arguments) });
    
    var totalCount = 0;
    for (var key in instance.formElements) totalCount++;
    
    // ...and if they do we will move onto the game
    if(count >= totalCount) {
        $('#ta-testet').removeClass("disabled").click(function() {
            $('#pre-game').fadeOut('fast');
            $('#header-pre').fadeOut('fast', function() {
                instance.startGame();

                $('html').keyup(function() { instance.onKey.apply(instance, arguments) });
            });
        });
    }
}

Handels.prototype.countElements = function(e, elem) {
    var instance = this;
    
    instance.formElements[elem.name] = !instance.formElements[elem.name] ? 1 : instance.formElements[elem.name] + 1;
}

Handels.prototype.checkCategory = function() {
    var instance = this;
    var valid = [];
    
    // if your keystroke matches the current word's category
    if(instance.triggeredSide == 'left') {
        valid = instance.activeCategory.left;
    } else if(instance.triggeredSide == 'right') {
        valid = instance.activeCategory.right;
    }
    
    for (var i=0; i < valid.length; i++) {
        if(!instance.activeWords[instance.wordPos]) return false;
        
        if(valid[i] == instance.activeWords[instance.wordPos].cat_id) return true;
    }
    
    return false;
}

Handels.prototype.processWord = function() {
    var instance = this;
    
    if(!instance.isStarted) return false; // don't check word if game is not started
    
    if(instance.checkCategory()) { // correct answer
        $('#error').stop().fadeTo(250, 0);
        
        if(instance.gotError) {
            instance.gotError = false;
            instance.activeWords[instance.wordPos].discard = true;
        }
        
        instance.wordStopped = new Date().getTime() - instance.wordStarted;

        instance.activeWords[instance.wordPos].time = instance.wordStopped;
        
        instance.correctAnswers = instance.correctAnswers+1;
    } else { // wrong answer
        $('#error').stop().fadeTo(250, 1);
        instance.gotError = true;
        return;
    }

    if(instance.correctAnswers < instance.activeWords.length) {
        instance.findNextWord(); // goes to next word
    } else {
        instance.summarizeStep(); // or summarizes the step when step is completed
    }
}

Handels.prototype.summarizeStep = function() {
    var instance = this;
    var totalTimeTaken = 0;
    
    var validAnswers = 0;
    
    for (var i=0; i < instance.activeWords.length; i++) {
        if(instance.activeWords[i].discard != true) {
            totalTimeTaken = totalTimeTaken + instance.activeWords[i].time;
            validAnswers = validAnswers + 1;
        }
    }
    
    instance.stepStopped = new Date().getTime() - instance.stepStarted;
    
    instance.steps[instance.step].stepTime = instance.stepStopped;
    instance.steps[instance.step].totalTime = totalTimeTaken;
    instance.steps[instance.step].totalTimeAvg = totalTimeTaken/validAnswers;
    
    instance.isStarted = false;
    instance.showedInfo = false;
    instance.step = instance.step + 1;
    
    instance.startGame();
}

Handels.prototype.finalSummary = function() {
    var instance = this;
    
    instance.isStarted = false;
    
    var postGame = $('#post-game');
    var timeStepDiff = 0;
    var timeHeader = '';
    var graphCaption = '';
        
    instance.windowHandler(postGame);
    instance.activeWindow = null;
    instance.returnWindow = $('#post-game');
    
    $('#header-pre').fadeOut('fast', function() {
        $('#header-post').fadeIn('fast');
    });
    
    timeStepDiff = (instance.steps[4].stepTime - instance.steps[2].stepTime);
    
    var percentDiff = Math.abs(roundNumber((1-(instance.steps[4].stepTime/instance.steps[2].stepTime))*100, 0));
    var femaleGraphHeight = 0;
    var maleGraphHeight = 0;
    
    if(timeStepDiff < 0)
    {
        timeHeader = 'Du har lättare att tänka dig kvinnor i karriären än i familjelivet.';
        graphCaption = 'Du var '+percentDiff+' % snabbare när KVINNA stod ihop med KARRIÄR och MAN med FAMILJ.';
        maleGraphHeight = 100;
        femaleGraphHeight = maleGraphHeight-(maleGraphHeight/(instance.steps[2].stepTime/1000));
    }
    else if(timeStepDiff > 0)
    {
        timeHeader = 'Du har lättare att tänka dig kvinnor i familjelivet än i karriären.';
        graphCaption = 'Du var '+percentDiff+' % långsammare när KVINNA stod ihop med KARRIÄR och MAN med FAMILJ.';
        femaleGraphHeight = 100;
        maleGraphHeight = femaleGraphHeight-(femaleGraphHeight/(instance.steps[4].stepTime/1000));
    }
    else if(timeStepDiff == 0)
    {
        timeHeader = 'Du gjorde ingen skillnad mellan KVINNA och MAN i relation till KARRIÄR eller FAMILJ.';
        graphCaption = '-';
        femaleGraphHeight = 100;
        maleGraphHeight = 100;
    }
    
    $('.result-header').text(timeHeader);
    
    $('.graph-caption').text(graphCaption);
    
    var maleTime = roundNumber(instance.steps[2].stepTime/1000, 2);
    var femaleTime = roundNumber(instance.steps[4].stepTime/1000, 2);
    
    $('.my-result .male-time').text(maleTime+' s');
    $('.my-result .female-time').text(femaleTime+' s');
    
    var height = graphHeight(maleTime, femaleTime);
    
    $('#post-game .my-result .male-graph').height(height['left']);
    $('#post-game .my-result .female-graph').height(height['right']);
    
    $('#detailed-results .my-result .male-graph').height(height['left']*2);
    $('#detailed-results .my-result .female-graph').height(height['right']*2);
    
    //var data = $("form#user-data").serialize()+'&total_time[]='+20301+'&step[]='+3+'&total_time[]='+29575+'&step[]='+4;
    var data = $("form#user-data").serialize()+'&step_time[]='+instance.steps[2].stepTime+'&step_time[]='+instance.steps[4].stepTime;
    
    //console.log(data);
    
    $.ajax({
        type: 'POST',
        url: 'ajax.php',
        data: data,
        success: function(data) {
            //console.log(data);
        },
        dataType: 'text'
    });
}

function graphHeight(left_value, right_value) {
    var left_height = 0;
    var right_height = 0;
    
	if(left_value > right_value) {
		left_height = 100;
		right_height = (right_value/left_value)*100;
	} else if(right_value > left_value) {
		left_height = (left_value/right_value)*100;
		right_height = 100;
	} else {
		left_height = 100;
		right_height = 100;
	}

	return {'left': left_height, 'right': right_height};
}

var roundNumber = function(num, dec) {
	return Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);;
}


$(document).ready(function() {
    var load = new LoadData(main);
    var handels = new Handels();
    
    function main(data) {
        handels.ready(data);
    }
});
