function InsertAt(pArray, pElement, nIndex)
{
  if (nIndex < 0 || nIndex > pArray.length)
    nIndex = pArray.length;

  for (var i = pArray.length; i >= nIndex + 1; i--)
    pArray[i] = pArray[i - 1];

  pArray[nIndex] = pElement;
}

function CreateIndexesInfo()
{
  for (var i = 0; i < g_pIndexes.length; i++)
  {
    var pIndex = g_pIndexes[i];
    var pInfo = new TestInfo(pIndex.m_name, pIndex.m_nodeName, 10000, "");

    pInfo.m_pIndex = pIndex;
    InsertAt(g_pMainTests, pInfo, i);
  }

  var pIndex = g_pStorageCardIndex;
  var pInfo = new TestInfo(pIndex.m_name, pIndex.m_nodeName, 10000, "");

  pInfo.m_pIndex = pIndex;
  InsertAt(g_pStorageCardTests, pInfo, 0);
}

function DevWithSCs(pDevice)
{
  this.m_pDevice = pDevice;
  this.m_pSCs = new Array();
  this.m_pSelectedSCs = new Object();
}

var g_pGraphWindow = null;
var g_pAddWindow = null;
var g_pDeviceParsersChain = new DeviceParsersChain(CompareDevices, null);
var g_pDevices = new Array();
var g_nMyDeviceCounter = 0;

CreateIndexesInfo();

function GetFullSCName(strDevName, strSCName)
{
  return strSCName + " (" + strDevName + ")";
}

function FillIndexValueForDevices(pInfo)
{
  if (!pInfo.m_pIndex)
    return 0;

  var nMinValue = null;
  var pDevicesResults = new Array();
  var pStdRootSec = g_pDeviceParsersChain.m_pHead.m_pObjDoc.documentElement;

  for (var p = g_pDeviceParsersChain.m_pHead.m_pNext; p != null; p = p.m_pNext)
  {
    if (!p.m_bSelected || !p.m_bOk)
      continue;

    var pRootSec = p.m_pObjDoc.documentElement;

    ClearIndexes();

    var dIndex = pInfo.m_pIndex.Calculate(pRootSec, pStdRootSec);

    if (dIndex > 0)
    {
      var nValue = 10000.0 / dIndex;

      if (nMinValue == null || nValue < nMinValue)
        nMinValue = nValue;

      pDevicesResults[pDevicesResults.length] = new Array(pInfo, "", nValue, p.m_pHeader.m_strName);
    }
    else
      pDevicesResults[pDevicesResults.length] = null;
  }

  pInfo.m_pDevicesResults = pDevicesResults;

  return nMinValue;
}

function FillTestValueForDevices(pInfo)
{
  if (pInfo.m_pIndex)
    return 0;

  var nMinValue = null;
  var pDevicesResults = new Array();

  for (var p = g_pDeviceParsersChain.m_pHead.m_pNext; p != null; p = p.m_pNext)
  {
    if (!p.m_bSelected || !p.m_bOk)
      continue;

    var pRootSec = p.m_pObjDoc.documentElement;
    var pMainSec = null;
    var pTestSec = null;

    if ((pMainSec = pRootSec.selectSingleNode("main-tests"))
      && (pTestSec = pMainSec.selectSingleNode(pInfo.m_nodeName)))
    {
      var nValue = parseFloat(pTestSec.text);

      if (isNaN(nValue) || nValue <= 0)
        nValue = null;
      else if (nMinValue == null || nValue < nMinValue)
        nMinValue = nValue;

      pDevicesResults[pDevicesResults.length] = new Array(pInfo, pTestSec.text, nValue, p.m_pHeader.m_strName);
    }
    else
      pDevicesResults[pDevicesResults.length] = null;
  }

  pInfo.m_pDevicesResults = pDevicesResults;

  return nMinValue;
}

function FillIndexValueForSCs(pInfo)
{
  if (!pInfo.m_pIndex)
    return 0;

  var nMinValue = null;
  var pDevicesResults = new Array();
  var pStdRootSec = g_pDeviceParsersChain.m_pHead.m_pObjDoc.documentElement;
  var pStdMainSec = pStdRootSec.selectSingleNode("main-tests");

  for (var i = 0; i < g_pDevices.length; i++)
  {
    var pDevice = g_pDevices[i];

    if (!pDevice)
      continue;

    for (var j = 0; j < pDevice.m_pSCs.length; j++)
    {
      var pSC = pDevice.m_pSCs[j];

      if (!pSC || !pDevice.m_pSelectedSCs[j])
        continue;

      ClearIndexes();

      var pCardNameSec = pSC.selectSingleNode("@card-name");
      var pRootSec = pDevice.m_pDevice.m_pObjDoc.documentElement;
      var dIndex = g_pStorageCardIndex.DoCalculate(pSC, pStdMainSec);
 
      if (dIndex > 0)
      {
        var nValue = 10000.0 / dIndex;
  
        if (nMinValue == null || nValue < nMinValue)
          nMinValue = nValue;
         
        pDevicesResults[pDevicesResults.length] = new Array(pInfo, "", nValue,
          GetFullSCName(pDevice.m_pDevice.m_pHeader.m_strName, pCardNameSec.text));
      }
      else
        pDevicesResults[pDevicesResults.length] = null;
    }
  }

  pInfo.m_pDevicesResults = pDevicesResults;

  return nMinValue;
}

function FillTestValueForSCs(pInfo)
{
  if (pInfo.m_pIndex)
    return 0;

  var nMinValue = null;
  var pDevicesResults = new Array();

  for (var i = 0; i < g_pDevices.length; i++)
  {
    var pDevice = g_pDevices[i];

    if (!pDevice)
      continue;

    for (var j = 0; j < pDevice.m_pSCs.length; j++)
    {
      var pSC = pDevice.m_pSCs[j];

      if (!pSC || !pDevice.m_pSelectedSCs[j])
        continue;

      var pCardNameSec = pSC.selectSingleNode("@card-name");
      var pTestSec = null;
  
      if (pTestSec = pSC.selectSingleNode(pInfo.m_nodeName))
      {
        var nValue = parseFloat(pTestSec.text);
  
        if (isNaN(nValue) || nValue <= 0)
          nValue = null;
        else if (nMinValue == null || nValue < nMinValue)
          nMinValue = nValue;
  
        pDevicesResults[pDevicesResults.length] = new Array(pInfo, pTestSec.text, nValue,
          GetFullSCName(pDevice.m_pDevice.m_pHeader.m_strName, pCardNameSec.text));
      }
      else
        pDevicesResults[pDevicesResults.length] = null;
    }
  }

  pInfo.m_pDevicesResults = pDevicesResults;

  return nMinValue;
}

function CompareDevices()
{
  var p = g_pDeviceParsersChain.m_pHead;

  if (!p)
    return;

  if (p && !p.m_bOk)
  {
    alert("Error parsing device XML");
    return;
  }

  document.all.d_main_compare_table_header.style.display = "";
  document.all.d_main_compare_table.innerHTML = HTMLCompareTable();

  document.all.d_main_compare_graphs_header.style.display = "";
  document.all.d_main_compare_graphs.innerHTML = HTMLLinksToGraphs();

  document.all.d_storage_cards_header.style.display = "";
  document.all.d_storage_cards_generate.style.display = "";
  document.all.d_storage_cards.innerHTML = HTMLCheckboxesForAllDevsAllSC();
  GenerateSCCompareTable();
}

function GenerateSCCompareTable()
{
  if (!g_pDeviceParsersChain.m_pHead)
    return;

  document.all.d_sc_compare_table_header.style,display = "";
  document.all.d_sc_compare_table.innerHTML = HTMLSCsCompareTable();

  document.all.d_sc_compare_graphs_header.style.display = "";
  document.all.d_sc_compare_graphs.innerHTML = HTMLSCLinksToGraphs();
}

function OpenAddDeviceWindow()
{
  if (g_pDeviceParsersChain.m_nState == DPS_IN_PROGRESS)
    return;

  g_pAddWindow = window.open("add_device.html",
    "addwin", "toolbar=0,location=0,status=1,menubar=0,scrollbars=1,resizable=1,width=600,height=400,top=150,left=150");
}

function InsertStdDevices()
{
  if (!checkSecuritySettings())
    return;

  g_pDeviceParsersChain.AddURL("http://spb.com/ext/benchmark/devices/iPAQ3600.xml");

  for (var i = 0; i < document.all.form_devices.elements.length; i++)
  {
    var strURL = "http://spb.com/ext/benchmark/devices/" + document.all.form_devices.elements[i].id + ".xml";

    g_pDeviceParsersChain.AddURL(strURL);
  }

  var strXML = document.all.form_device.ta_device.value;

  if (strXML != "")
    AddDeviceToList(strXML);
  else
    StartCompareDevices();
}

function UpdateSelectedDevices()
{
  var p = g_pDeviceParsersChain.m_pHead.m_pNext;

  for (var i = 0; i < document.all.form_devices.elements.length && p != null; i++, p = p.m_pNext)
  {
    var bSelected = document.all.form_devices.elements[i].checked;

    p.m_bSelected = bSelected;
  }
}

function StartCompareDevices()
{
  if (!checkSecuritySettings())
    return;

  if (g_pDeviceParsersChain.m_nState == DPS_IN_PROGRESS)
    return;

  UpdateSelectedDevices();

  do {

  if (g_pDeviceParsersChain.GetSelectedCount() < 2) break;

  g_pDeviceParsersChain.Run();

  return;

  } while (false);

  alert("There should be at least 2 different devices to compare");
}

function HTMLCheckboxFor1SC(pDevice, pSec, nDeviceIndex, nSCIndex)
{
  do {

  if (pSec == null)
    break;

  var res = "";
  var pCardNameSec = pSec.selectSingleNode("@card-name");

  if (!pCardNameSec || pCardNameSec.text == "")
    break;

  res += "<input type='checkbox' id='sc_" + nDeviceIndex + "_" + nSCIndex + "'>";
  res += "<label for='sc_" + nDeviceIndex + "_" + nSCIndex + "'>"
    + GetFullSCName(pDevice.m_pHeader.m_strName, pCardNameSec.text)
    + "</label><br>";

  return res;

  } while (false);

  return "";
}

function HTMLCheckboxesFor1DevAllSC(pDevWithSCs, nDeviceIndex)
{
  do {

  if (!pDevWithSCs || !pDevWithSCs.m_pDevice || !pDevWithSCs.m_pDevice.m_pObjDoc)
    break;

  var pSec = pDevWithSCs.m_pDevice.m_pObjDoc.documentElement;

  if (pSec == null)
      break;

  var pSCsSec = pSec.selectSingleNode("storagecard-tests");

  if (!pSCsSec)
    break;
      
  var res = "";
  var pList = pSCsSec.selectNodes("storagecard-test");

  if (!pList)
    break;

  pDevWithSCs.m_pSCs = pList;

  var bListEmpty = true;

  for (var i = 0; i < pList.length; i++)
  {
    var pCardSec = pList[i];
    var res1SC = HTMLCheckboxFor1SC(pDevWithSCs.m_pDevice, pCardSec, nDeviceIndex, i);

    if (res1SC == "")
      continue;

    res += res1SC;

    bListEmpty = false;
  }

  if (bListEmpty)
    break;

  return res;

  } while (false);

  return "";
}

function HTMLCheckboxesForAllDevsAllSC()
{
  g_pDevices = new Array();

  var res = "";

  res += "<hr size=1 noshade style='margin-left: 16px; margin-right: 16px'>";
  res += "<form id='form_storage_cards'>";
  res += "<p>";

  var bListEmpty = true;
  var nDeviceIndex = 0;

  for (var p = g_pDeviceParsersChain.m_pHead.m_pNext; p != null; p = p.m_pNext, nDeviceIndex++)
  {
    g_pDevices[nDeviceIndex] = null;

    if (!p.m_bOk)
      continue;

    var pDevWithSCs = new DevWithSCs(p);
    var res1Dev = HTMLCheckboxesFor1DevAllSC(pDevWithSCs, nDeviceIndex);

    if (res1Dev != "")
    {
      g_pDevices[nDeviceIndex] = pDevWithSCs;
      bListEmpty = false;
    }

    res += res1Dev;
  }

  res += "</p>";
  res += "</form>";

  if (bListEmpty)
    return "";

  return res;
}

function HTMLResultsOfTest(pInfo, nSelectValue)
{
  if (!pInfo || !pInfo.m_pDevicesResults)
    return "";

  var res = "";

  for (var j = 0; j < pInfo.m_pDevicesResults.length; j++)
  {
    var pResult = pInfo.m_pDevicesResults[j];

    if (!pResult)
    {
      res += "<td class='ct' align='center'><table border=0 width=10 height=1 cellpadding=0 cellspacing=0 bgcolor='#000000'><tr><td></td></tr></table></td>";
      continue;
    }

    var strText = pResult[1];
    var nValue = pResult[2];

    if (nValue)
    {
      res += "<td class='ct' align='center'>";

      if (nValue == nSelectValue)
        res += "<font color='#202078'><b>";

      res += SmartFloatToString(pInfo.m_coef * 1.0 / nValue, 0) + "</td>";

      if (nValue == nSelectValue)
        res += "</b></font>";

      res += "</td>";
    }
    else
      res += "<td class='ct' align='center'><font color='#FF0000'>" + strText + "&nbsp;</font></td>";
  }

  return res;
}

function HTMLCompareTable()
{
  var res = "";

  var nDevicesCount = 0;

  res += "<table class='ctable' border=1 cellpadding=5 cellspacing=1 width=1><tr><td class='ct'>&nbsp;</td>";

  for (var p = g_pDeviceParsersChain.m_pHead.m_pNext; p != null; p = p.m_pNext)
  {
    if (!p.m_bSelected || !p.m_bOk)
      continue;

    res += "<td class='ct'>" + p.m_pHeader.m_strName + "</td>";
    nDevicesCount++;
  }

  res += "</tr>";

  for (var i = 0; i < g_pMainTests.length; i++)
  {
    var pInfo = g_pMainTests[i];

    res += "<tr>";
    res += "<td class='ct' nowrap><a href='' onclick=\"OpenHelpWindow('" + pInfo.m_nodeName + "'); return false\">";

    if (pInfo.m_pIndex)
    {
      if (pInfo.m_pIndex == g_pSpbIndex)
        res += "<font color='#FF0000'>";

      res += "<b>" + pInfo.m_name + "</b>";

      if (pInfo.m_pIndex == g_pSpbIndex)
        res += "</font>";
    }
    else
      res += pInfo.m_name + " (" + pInfo.m_unit + ")";

    res += "</a></td>";

    var nMinValue = null;

    if (pInfo.m_pIndex)
      nMinValue = FillIndexValueForDevices(pInfo);
    else
      nMinValue = FillTestValueForDevices(pInfo);

    res += HTMLResultsOfTest(pInfo, nMinValue);
    res += "</tr>";
  }

  res += "</table>";

  return res;
}

function HTMLSCsCompareTable()
{
  var res = "";

  var nSCsCount = 0;

  res += "<table class='ctable' border=1 cellpadding=5 cellspacing=1><tr><td class='ct'>&nbsp;</td>";

  for (var i = 0; i < g_pDevices.length; i++)
  {
    var pDevice = g_pDevices[i];

    if (!pDevice)
      continue;

    for (var j = 0; j < pDevice.m_pSCs.length; j++)
    {
      var pSC = pDevice.m_pSCs[j];

      if (!pSC)
        continue;

      pDevice.m_pSelectedSCs[j] = 1;

      var pCB = document.all.form_storage_cards["sc_" + i + "_" + j];

      if (!pCB || !pCB.checked)
      {
        pDevice.m_pSelectedSCs[j] = null;
        continue;
      }

      var pCardNameSec = pSC.selectSingleNode("@card-name");

      res += "<td class='ct'>" + GetFullSCName(pDevice.m_pDevice.m_pHeader.m_strName, pCardNameSec.text) + "</td>";
      nSCsCount++;
    }
  }

  res += "</tr>";

  for (var k = 0; k < g_pStorageCardTests.length; k++)
  {
    var pInfo = g_pStorageCardTests[k];

    res += "<tr>";
    res += "<td class='ct' nowrap><a href='' onclick=\"OpenHelpWindow('" + pInfo.m_nodeName + "'); return false\">";

    if (pInfo.m_pIndex)
      res += "<b>" + pInfo.m_name + "</b>";
    else
      res += pInfo.m_name + " (" + pInfo.m_unit + ")";

    res += "</a></td>";

    var nMinValue = null;

    if (pInfo.m_pIndex)
      nMinValue = FillIndexValueForSCs(pInfo);
    else
      nMinValue = FillTestValueForSCs(pInfo);

    res += HTMLResultsOfTest(pInfo, nMinValue);
    res += "</tr>";
  }

  res += "</table>";

  return res;
}

function OpenGraph(nTestIndex, bStorageCards)
{
  if (nTestIndex < 0)
    return;

  if (!bStorageCards && nTestIndex >= g_pMainTests.length)
    return;

  if (bStorageCards && nTestIndex >= g_pStorageCardTests.length)
    return;

  g_pGraphWindow = window.open("compare_graph.html?test=" + nTestIndex + (bStorageCards ? "&sc=1" : ""),
    "graphwin", "toolbar=0,location=0,status=1,menubar=0,scrollbars=1,resizable=1,width=600,height=600,top=50,left=50");
}

function HTMLLinksToGraphs()
{
  var res = "";

  res += "<p>";
  res += "<ul>";

  for (var i = 0; i < g_pMainTests.length; i++)
  {
    var pInfo = g_pMainTests[i];

    res += "<li><a href='' onclick='OpenGraph(" + i + "); return false'>";

    var strLink = "Graph for " + pInfo.m_name + (pInfo.m_pIndex ? "" : " test");

    if (pInfo.m_pIndex)
    {
      if (pInfo.m_pIndex == g_pSpbIndex)
        res += "<font color='#FF0000'>";

      res += "<b>" + strLink + "</b>";

      if (pInfo.m_pIndex == g_pSpbIndex)
        res += "</font>";
    }
    else
      res += strLink;
    
    res += "</a></li>";
  }

  res += "</ul>";
  res += "</p>";

  return res;
}

function HTMLSCLinksToGraphs()
{
  var res = "";

  res += "<p>";
  res += "<ul>";

  for (var i = 0; i < g_pStorageCardTests.length; i++)
  {
    var pInfo = g_pStorageCardTests[i];

    res += "<li><a href='' onclick='OpenGraph(" + i + ", true); return false'>";

    var strLink = "Graph for " + pInfo.m_name + (pInfo.m_pIndex ? "" : " test");

    if (pInfo.m_pIndex)
      res += "<b>" + strLink + "</b>";
    else
      res += strLink;
    
    res += "</a></li>";
  }

  res += "</ul>";
  res += "</p>";

  return res;
}

function HTMLMyDevice(strName)
{
  var res = "";

  res += "<div class='techdiv' id='" + g_nMyDeviceCounter + "'>";
  res += "<p>My device (" + strName + ")&nbsp;";
  res += "<a href='' onclick='DeleteDevice(this.parentElement.parentElement); return false'>Delete device</a></p>";
  res += "</div>";

  return res;
}

function AddDeviceToList(strXML)
{
  if (g_pDeviceParsersChain.m_nState == DPS_IN_PROGRESS)
    return;

  var pDeviceParser = new DeviceParser(strXML, null);

  pDeviceParser.Run();

  if (!pDeviceParser.m_bOk)
  {
    alert("Error parsing device XML");
    return;
  }

  g_pDeviceParsersChain.Add(pDeviceParser);
  g_nMyDeviceCounter++;
  pDeviceParser.m_nID = g_nMyDeviceCounter;

  var pDevDivs = document.all.d_mydevices.children;
  var strName = pDeviceParser.m_pHeader.m_strName;

  document.all.d_mydevices.innerHTML += HTMLMyDevice(strName);
  StartCompareDevices();
}

function DeleteDevice(pDiv)
{
  if (!pDiv)
    return;

  var nID = pDiv.id;

  g_pDeviceParsersChain.Delete(nID);

  pDiv.outerHTML = "";
  StartCompareDevices();
}

function DoUnload()
{
  if (g_pGraphWindow != null && !g_pGraphWindow.closed)
  {
    g_pGraphWindow.close();
    g_pGraphWindow = null;
  }

  if (g_pAddWindow != null && !g_pAddWindow.closed)
  {
    g_pAddWindow.close();
    g_pAddWindow = null;
  }

  CloseHelpWindow();
}

