// Different modes the game can be in
var CURRENT_GAME_MODE;
var PRACTICE_MODE = 0;
var COMPETE_MODE = 1;

// Status of a user. Same globals as in users.py
var STATUS_OFFLINE = 0;
var STATUS_ONLINE = 1;
var STATUS_BUSY = 2;

// Status of a competition. Same globals as competitions.py
var STATUS_CREATED = 0;
var STATUS_OFFERED = 1;
var STATUS_CANCELLED = 2;
var STATUS_ACCEPTED = 3;
var STATUS_REJECTED = 4;
var STATUS_FINISHED = 5;

var PENDING_POINTS = 0; // Number of points pending for the current problem
var INPUT_QUEUE = []; // Client-side queue to record inputs
var USER_INPUT = []; // Raw input include kcode and x, y locations

// Used to handle number keypad in various browsers
var KEY_MAP = {
  // Mozilla & IE Keypad
  96 : 48, 45 : 48, // keypad 0
  97 : 49, 35 : 49, // keypad 1
  98 : 50, 40 : 50, // keypad 2
  99 : 51, 34 : 51, // keypad 3
  100 : 52, 37 : 52, // keypad 4
  101 : 53, 12 : 53, // keypad 5
  102 : 54, 39 : 54, // keypad 6
  103 : 55, 36 : 55, // keypad 7
  104 : 56, 38 : 56, // keypad 8
  105 : 57, 33 : 57,  // keypad 9
  
  // Shifted key line values
  41 : 48, // )
  33 : 49, // !
  64 : 50, // @
  35 : 51, // #
  36 : 52, // $
  37 : 53, // %
  94 : 54, // ^
  38 : 55, // &
  42 : 56, // *
  40 : 57  // (
}

window.onbeforeunload = onBeforeUnload;

// Function called right before the page is unloaded
function onBeforeUnload() {
  if (location.pathname == "/play") {
    changeStatus(STATUS_OFFLINE, false);
  }
}

// Adds callback for DOM ready
$(document).ready(playDomReady);

// Function to call when the DOM is ready for manipulation.
function playDomReady() {
  if (location.pathname == "/play") {
    setupUserWorkspace();
    setupOpponentWorkspace();
  }
}

function setupUserWorkspace() {
  if (WORKSPACE == null) {
    try {
      initializeUserWorkspace();
    }
    catch(err) { }
    setTimeout(setupUserWorkspace, 100);
  }
  else {
  	WORKSPACE.addEventListener("workspaceFinished", workspaceProblemFinished);
  	WORKSPACE.addEventListener("newHelpMessage", newHelpMessage);
    WORKSPACE.addEventListener("clearHelpMessage", clearHelpMessage);
    setupInputHandlers();
  }
}

function setupOpponentWorkspace() {
  if (OPPONENT == null) {
    try {
      initializeOpponentWorkspace();      
    }
    catch(err) { }
    setTimeout(setupOpponentWorkspace, 100);
  }
  else {
    OPPONENT.addEventListener("workspaceFinished", opponentProblemFinished);
  }
}

function workspaceProblemFinished() {
  if (CURRENT_GAME_MODE == PRACTICE_MODE) {
    setTimeout(practiceProblemFinishedAfterTimeout, 0);
  }
  else if (CURRENT_GAME_MODE == COMPETE_MODE) {
    setTimeout(competitionProblemFinishedAfterTimeout, 0);
  }
}

function opponentProblemFinished() {
  if (CURRENT_GAME_MODE == COMPETE_MODE) {
    setTimeout(opponentProblemFinishedAfterTimeout, 0);
  }
}

// Runs the actual problem given a workspace to run it in
function runProblem(workspace, problem) {
  workspace.hideProblem();
  problemClass = (problem.problem_type.toLowerCase() + "." +
                  problem.problem_type + 
                  problem.algorithm + "Algorithm");
  workspace.setProblem(problemClass, 
                       problem.operands,
                       problem.addnl_params,
                       problem.user_vars);
  workspace.runProblem();      
}

// Adds a space character before every capitalized letter except the first.
function addSpaceBeforeCap(str) {
  if (str.length < 2) return str;
  else {
    newStr = str.charAt(0);
    for (i = 1; i < str.length; i++) {
      if (str.charAt(i) == str.charAt(i).toUpperCase()) {
        newStr += " ";
      }
      newStr += str.charAt(i);
    }
    return newStr;
  }
}

// Idea from: http://www.kelvinluck.com/assets/jquery/styleswitch/index.html
function switchStylesheet(styleName)
{
	$('link[@rel*=style][title]').each(function(i) 
	{
		this.disabled = true;
		if (this.getAttribute('title') == styleName) this.disabled = false;
	});
}

// Event listener for whenever the user enters input for the current problem.
function problemInput(response) {
  if (response && response.getIsCorrect() > 0) {
    if (CURRENT_GAME_MODE == PRACTICE_MODE) {
      practiceProblemInput(response);         
    }
    else if (CURRENT_GAME_MODE == COMPETE_MODE) {
      competeProblemInput(response);
    }
  }
}

// Function to setup input handlers
function setupInputHandlers() {
  $(document).bind("keydown", keyDown);
  $(document).bind("keypress", keyPress);
  $(document).bind("contextmenu", killEvent);
  $(document).bind("mousedown", mouseDown);
}

// Function to kill an event from proprogating
function killEvent(eventObject) {
  if (eventObject && eventObject.stopPropagation)
    eventObject.stopPropagation();

  if (window.event && window.event.cancelBubble ) 
    window.event.cancelBubble = true;

  if (eventObject && eventObject.preventDefault) 
    eventObject.preventDefault();

  if (window.event) 
    window.event.returnValue = false;

  if(eventObject.preventCapture) 
    eventObject.preventCapture();

  if(eventObject.preventBubble) 
    eventObject.preventBubble();
}

// Callback for when a key down occurs
function keyDown(eventObject) {
  if ($(".jqmOverlay").length == 0) {
    kcode = eventObject.keyCode;

    if (kcode == 8) {
      // Backspace key was entered so kill it before it causes browser to
      // go back in navigation history.
      problemInput(WORKSPACE.handleKeyboardInput(kcode));
      killEvent(eventObject);
      return false;
    }
  }
}

// Callback for when a key press occurs
function keyPress(eventObject) {
  if ($(".jqmOverlay").length == 0) {
    if (eventObject.charCode) {
      kcode = eventObject.charCode;      
    }
    else {
      kcode = eventObject.keyCode;
    }
    
    if (kcode in KEY_MAP) {
      kcode = KEY_MAP[kcode];
    }

    if (kcode > 0) {
      if (kcode != 8) {
        response = WORKSPACE.handleKeyboardInput(kcode);
        if (response != null) {
          USER_INPUT.push(kcode);
        }
        problemInput(response);
      }
    }
    else {
      killEvent(eventObject);
      return false;
    }
  }
}


// Callback for when a mouse down event occurs
function mouseDown(eventObject) {
  if ($(".jqmOverlay").length == 0) {
    x = eventObject.pageX;
    y = eventObject.pageY;

    response = WORKSPACE.handleMouseInput(x, y);
    if (response != null) {
      unscaledX = (x - WORKSPACE.getPaddingLeft()) / WORKSPACE.getScaleX();
      unscaledY = (y - WORKSPACE.getPaddingTop()) / WORKSPACE.getScaleY();
      USER_INPUT.push([unscaledX, unscaledY]);
    }
    problemInput(response);
    
    if (eventObject.button != 0) {
      killEvent(eventObject);
      return false;
    }
  }
}

