﻿var testIsRunning = false, preCreatedElements = [];
jQuery(function () {
  //Binding the event witch will start the simple test
  jQuery("#runTests").click(function () {
    //Henter antal
    if (!testIsRunning) {
      testIsRunning = true;
      var numberOfElements = parseInt(jQuery("#numberOfElements").val());
      runAllTests(numberOfElements, "appendTests", "resultsTable");
    }
  });
  //Binding the event witch will start the advanced test
  jQuery("#runAdvancedTests").click(function () {
    if (!testIsRunning) {
      testIsRunning = true;
      var numberOfElements = parseInt(jQuery("#numberOfElementsAdvanced").val());
      runAllTests(numberOfElements, "advancedAppendTests", "advancedResultsTable");
    }
  });
  //Binding the event witch will start the advanced test
  jQuery("#runTestsNoEleCreation").click(function () {
    if (!testIsRunning) {
      testIsRunning = true;
      var numberOfElements = parseInt(jQuery("#numberOfElementsNoEleCreation").val());
      runAllTests(numberOfElements, "appendTestsNoEleCreation", "resultsTableNoEleCreation", true);
    }
  });
  //Binding the event witch will start the advanced test
  jQuery("#runAdvancedTestsNoEleCreation").click(function () {
    if (!testIsRunning) {
      testIsRunning = true;
      var numberOfElements = parseInt(jQuery("#numberOfElementsAdvancedNoEleCreation").val());
      runAllTests(numberOfElements, "advancedAppendTestsNoEleCreation", "advancedResultsTableNoEleCreation", true);
    }
  });
});
/*
* Starts all tests of a certain type
*/
function runAllTests(numberOfElements, testMethodsName, resultsTableID, preCreateElements) {
  //The results table is cleared
  jQuery('#' + resultsTableID + ' tr:not(:first)').remove();
  //A Timeout secures the stability of the tests as the browsers will treat each test as a new process with its's own timeout period
  window.setTimeout('initializeTest(' + numberOfElements + ', "' + testMethodsName + '", "' + resultsTableID + '", ' + preCreateElements + ')', 10);
}
/*
* Initialises a series of tests with a given number of elements to create
*/
function initializeTest(numberOfElements, testMethodsName, resultsTableID, preCreateElements) {
  var testResultTable = jQuery('#' + resultsTableID),
      currentTr = testResultTable.find("tr:last"), 
      timeTaken = -1;
  //Starts the new table row
  currentTr = jQuery(document.createElement("tr"));
  currentTr.append('<td>' + numberOfElements + '</td>');
  testResultTable.append(currentTr);
  //Readies the first test in the series in a timeout
  window.setTimeout('runTest("test01", ' + numberOfElements + ', "' + testMethodsName + '", "' + resultsTableID + '", ' + preCreateElements + ')', 10);
}
/*
* Runs a test and then readies the next test
*/
/*
    appendTestsNoEleCreation = [],
    appendTestsNoEleCreationPreCreate = [],
    advancedAppendTestsNoEleCreation = [],
    advancedAppendTestsNoEleCreationPreCreate = [];

*/
function runTest(createMethodName, numberOfElements, testMethodsName, resultsTableID, preCreateElements) {
  if (preCreateElements) {
    preCreatedElements = window[testMethodsName + "PreCreate"][createMethodName](numberOfElements);
    var t = preCreatedElements;
  }
  var testResultTable = jQuery('#' + resultsTableID),
      currentTr = testResultTable.find("tr:last"),
      timeTaken = -1,
      insertIntoEle = jQuery("#insertIntoEle .insertIntoEle").html(""),
      startTime = (new Date()).getTime();
  //Gets the current set of tests (Simple or advanced)
  testMethods = window[testMethodsName];
  //Runs the current test
  testMethods[createMethodName](insertIntoEle, numberOfElements)
  //Clocks the runtime of the test
  timeTaken = (new Date()).getTime() - startTime;
  //Appends the test result to the test restult table
  currentTr.append('<td result="' + timeTaken + '">' + timeTaken + ' ms</td>');
  var currentMethodFound = false;
  //Find the next test
  for (methodName in testMethods) {
    if (currentMethodFound) {
      //The next test is found and is now being readied to run
      window.setTimeout('runTest("' + methodName + '", ' + numberOfElements + ', "' + testMethodsName + '", "' + resultsTableID + '", ' + preCreateElements + ')', 10);
      return;
    }
    //Checks to find the current test
    currentMethodFound = methodName === createMethodName;
  }
  //If we get to this point, no more tests can be run
  //Mark the looser and winner tests in the test result table
  markWinnerResult(resultsTableID);
  //If the number of elements have been counted down to 1, no mores tests can be run
  if (numberOfElements === 1) {
    testIsRunning = false;
    return;
  }
  //Number of elements is halved for the next test series
  numberOfElements = Math.ceil(numberOfElements / 2);
  //Next test series initialization is readied
  window.setTimeout('initializeTest(' + numberOfElements + ', "' + testMethodsName + '", "' + resultsTableID + '", ' + preCreateElements + ')', 10);
}
/*
* Below starts the actual tests
*/
//Two arrays are created to hold the variable number of tests
var appendTests = [],
    advancedAppendTests = [],
    appendTestsNoEleCreation = [],
    appendTestsNoEleCreationPreCreate = [],
    advancedAppendTestsNoEleCreation = [],
    advancedAppendTestsNoEleCreationPreCreate = [];
//Simple test 1
appendTests["test01"] = function test01(insertIntoEle, numberOfElements) {
  var ele = null;
  for (var i = 0; i < numberOfElements; i++) {
    jQuery("#insertIntoEle .insertIntoEle").append(createSimpleEle(i));
  }
};
//Simple test 2
appendTests["test02"] = function test02(insertIntoEle, numberOfElements) {
  var ele = null;
  for (var i = 0; i < numberOfElements; i++) {
    insertIntoEle.append(createSimpleEle(i));
  }
};
//Simple test 3
appendTests["test03"] = function test03(insertIntoEle, numberOfElements) {
  var ele = null, jQContainer = jQuery("<dl>");
  for (var i = 0; i < numberOfElements; i++) {
    ele = createSimpleEle(i);
    jQContainer.append(ele);
  }
  insertIntoEle.append(jQContainer.children());
};
//Simple test 4
appendTests["test04"] = function (insertIntoEle, numberOfElements) {
  var ele = "";
  for (var i = 0; i < numberOfElements; i++) {
    ele += createSimpleEle(i, true);
  }
  insertIntoEle.append(ele);
};
//Simple test 5
appendTests["test05"] = function (insertIntoEle, numberOfElements) {
  var ele = jQuery([]);
  for (var i = 0; i < numberOfElements; i++) {
    ele = ele.add(createSimpleEle(i));
  }
  insertIntoEle.append(ele);
};
//Advanced test 1
advancedAppendTests["test01"] = function (insertIntoEle, numberOfElements) {
  var ele = null;
  for (var i = 0; i < numberOfElements; i++) {
    jQuery("#insertIntoEle .insertIntoEle").append(createAdvancedEle(i));
  }
};
//Advanced test 2
advancedAppendTests["test02"] = function (insertIntoEle, numberOfElements) {
  var ele = null;
  for (var i = 0; i < numberOfElements; i++) {
    var newEle = jQuery(document.createElement("dd"));
    insertIntoEle.append(createAdvancedEle(i));
  }
};
//Advanced test 3
advancedAppendTests["test03"] = function (insertIntoEle, numberOfElements) {
  var ele = null, jQContainer = jQuery("<dl>");
  for (var i = 0; i < numberOfElements; i++) {
    jQContainer.append(createAdvancedEle(i));
  }
  insertIntoEle.append(jQContainer.children());
};
//Advanced test 4
advancedAppendTests["test04"] = function (insertIntoEle, numberOfElements) {
  var ele = "";
  for (var i = 0; i < numberOfElements; i++) {
    ele += createAdvancedEle(i, true);
  }
  insertIntoEle.append(ele);
};
//Advanced test 5
advancedAppendTests["test05"] = function (insertIntoEle, numberOfElements) {
  var ele = jQuery([]);
  for (var i = 0; i < numberOfElements; i++) {
    ele = ele.add(createAdvancedEle(i));
  }
  insertIntoEle.append(ele);
};
/********************************************************************************************/

//Simple NoEleCreation test 1
appendTestsNoEleCreation["test01"] = function test01(insertIntoEle, numberOfElements) {
  var ele = null;
  for (var i = 0; i < numberOfElements; i++) {
    jQuery("#insertIntoEle .insertIntoEle").append(preCreatedElements[i]);
  }
};
appendTestsNoEleCreationPreCreate["test01"] =
appendTestsNoEleCreationPreCreate["test02"] = function test01(numberOfElements) {
  preCreatedElements = [];
  for (var i = 0; i < numberOfElements; i++) {
    preCreatedElements.push(createSimpleEle(i));
  }
  return preCreatedElements;
};
//Simple NoEleCreation test 2
appendTestsNoEleCreation["test02"] = function (insertIntoEle, numberOfElements) {
  var ele = null;
  for (var i = 0; i < numberOfElements; i++) {
    insertIntoEle.append(preCreatedElements[i]);
  }
};
//Simple NoEleCreation test 3
appendTestsNoEleCreation["test03"] = function (insertIntoEle, numberOfElements) {
  insertIntoEle.append(preCreatedElements.children());
};
appendTestsNoEleCreationPreCreate["test03"] = function test01(numberOfElements) {
  var ele = null, preCreatedElements = jQuery("<dl>");
  for (var i = 0; i < numberOfElements; i++) {
    preCreatedElements.append(createSimpleEle(i));
  }
  return preCreatedElements;
};
//Simple NoEleCreation test 4
appendTestsNoEleCreation["test04"] = function (insertIntoEle, numberOfElements) {
  insertIntoEle.append(preCreatedElements);
};
appendTestsNoEleCreationPreCreate["test04"] = function (numberOfElements) {
  preCreatedElements = "";
  for (var i = 0; i < numberOfElements; i++) {
    preCreatedElements += createSimpleEle(i, true);
  }
  return preCreatedElements;
};
//Simple NoEleCreation test 5
appendTestsNoEleCreation["test05"] = function (insertIntoEle, numberOfElements) {
  insertIntoEle.append(preCreatedElements);
};
appendTestsNoEleCreationPreCreate["test05"] = function (numberOfElements) {
  preCreatedElements = jQuery([]);
  for (var i = 0; i < numberOfElements; i++) {
    preCreatedElements = preCreatedElements.add(createSimpleEle(i));
  }
  return preCreatedElements;
};

/*
    appendTestsNoEleCreation = [],
    advancedAppendTestsNoEleCreation = [];
    appendTestsNoEleCreationPreCreate = [],
    advancedAppendTestsNoEleCreationPreCreate = [];

*/

//Advanced NoEleCreation test 1
advancedAppendTestsNoEleCreation["test01"] = function (insertIntoEle, numberOfElements) {
  var ele = null;
  for (var i = 0; i < numberOfElements; i++) {
    jQuery("#insertIntoEle .insertIntoEle").append(preCreatedElements[i]);
  }
};
advancedAppendTestsNoEleCreationPreCreate["test01"] =
advancedAppendTestsNoEleCreationPreCreate["test02"] = function (numberOfElements) {
  preCreatedElements = [];
  for (var i = 0; i < numberOfElements; i++) {
    preCreatedElements.push(createAdvancedEle(i));
  }
  return preCreatedElements;
};
//Advanced NoEleCreation test 2
advancedAppendTestsNoEleCreation["test02"] = function (insertIntoEle, numberOfElements) {
  var ele = null;
  for (var i = 0; i < numberOfElements; i++) {
    insertIntoEle.append(preCreatedElements[i]);
  }
};
//Advanced NoEleCreation test 3
advancedAppendTestsNoEleCreation["test03"] = function (insertIntoEle, numberOfElements) {
  insertIntoEle.append(preCreatedElements.children());
};
advancedAppendTestsNoEleCreationPreCreate["test03"] = function (numberOfElements) {
  var ele = null, preCreatedElements = jQuery("<dl>");
  for (var i = 0; i < numberOfElements; i++) {
    preCreatedElements.append(createAdvancedEle(i));
  }
  return preCreatedElements;
};
//Advanced NoEleCreation test 4
advancedAppendTestsNoEleCreation["test04"] = function (insertIntoEle, numberOfElements) {
  insertIntoEle.append(preCreatedElements);
};
advancedAppendTestsNoEleCreationPreCreate["test04"] = function ( numberOfElements) {
  preCreatedElements = "";
  for (var i = 0; i < numberOfElements; i++) {
    preCreatedElements += createAdvancedEle(i, true);
  }
  return preCreatedElements;
};
//Advanced NoEleCreation test 5
advancedAppendTestsNoEleCreation["test05"] = function (insertIntoEle, numberOfElements) {
  insertIntoEle.append(preCreatedElements);
};
advancedAppendTestsNoEleCreationPreCreate["test05"] = function (numberOfElements) {
  preCreatedElements = jQuery([]);
  for (var i = 0; i < numberOfElements; i++) {
    preCreatedElements = preCreatedElements.add(createAdvancedEle(i));
  }
  return preCreatedElements;
};

/********************************************************************************************/
//A method for creating the advanced elements. This ensures that they are alike every time.
function createAdvancedEle(i, createHtml) {
  var newEle;
  if (createHtml) {
    newEle = '<dd id="eleID' + i + '" class="eleClass">Some text followed by a link<a href="http://rune.gronkjaer.dk">Runes blog</a></dd>';
  } else {
    newEle = jQuery(document.createElement("dd"));
    newEle.html('Some text followed by a link <a href="http://rune.gronkjaer.dk">Runes blog</a>')
          .attr("id", "eleID" + i)
          .attr("someWeirdAttribute", "someWeirdAttributeContent")
          .addClass("eleClass");
  }
  return newEle;
}
//A method for creating the simple elements. This ensures that they are alike every time.
function createSimpleEle(i, createHtml) {
  var newEle;
  if (createHtml) {
    newEle = '<dd></dd>';
  } else {
    newEle = jQuery(document.createElement("dd"));
  }
  return newEle;
}
//Helping method for marking the winning and loosing test of each test series
function markWinnerResult(resultsTableID) {
  var winner = -1, looser = -1, results = jQuery('#' + resultsTableID + ' tr:last td:not(:first)');
  for (var i = 0; i < results.length; i++) {
    var thisResult = parseInt(jQuery(results[i]).attr("result"));
    if (winner === -1 || winner > thisResult) {
      winner = thisResult;
    }
    if (looser < thisResult) {
      looser = thisResult;
    }
  }
  results.filter("[result=" + winner + "]").addClass("winner");
  results.filter("[result=" + looser + "]").addClass("looser");
}
