<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="/tests/SimpleTest/test.css" type="text/css"?>

<window title="Toolbar" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
        onload="startTest();">

  <script type="application/javascript" src="/MochiKit/packed.js"></script>
  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>

  <toolbox id="toolbox">
    <toolbarpalette>
      <toolbarbutton id="p1" label="p1"/>
      <toolbarbutton id="p2" label="p2"/>
      <toolbarbutton id="p3" label="p3"/>
      <toolbarbutton id="p4" label="p4"/>
      <toolbarbutton id="p5" label="p5"/>
      <toolbarbutton id="p6" label="p6"/>
      <toolbarbutton id="p7" label="p7"/>
      <toolbarbutton id="p8" label="p8"/>
      <toolbarbutton id="p9" label="p9"/>
      <toolbarbutton id="p10" label="p10"/>
      <toolbarbutton id="p11" label="p11"/>
      <toolbarbutton id="p12" label="p12"/>
    </toolbarpalette>

    <toolbar id="tb1" defaultset="p1,p2"/>
    <toolbar id="tb2" defaultset="p4,p3"/>
    <toolbar id="tb3" defaultset="p5,p6,t31">
      <toolbarbutton id="t31" label="t31" removable="true"/>
    </toolbar>
    <toolbar id="tb4" defaultset="t41,p7,p8">
      <toolbarbutton id="t41" label="t41" removable="true"/>
    </toolbar>
    <toolbar id="tb5" defaultset="p9,t51,p10">
      <toolbarbutton id="t51" label="t51" removable="true"/>
    </toolbar>

    <toolbar id="tb-test" defaultset="p11,p12"/>
    <toolbar id="tb-test2" defaultset=""/>
    <!-- fixed toolbarbuttons always have 'fixed' in their id -->
    <toolbar id="tb-test3" defaultset="">
      <toolbarbutton id="tb-fixed-1" label="tb-test3-1"/>
      <toolbarbutton id="tb-fixed-2" label="tb-test3-2" removable="false"/>
      <toolbarbutton id="tb-fixed-3" label="tb-test3-3"/>
    </toolbar>
  </toolbox>

  <toolbar id="notoolbox"/>

  <!-- test resuls are displayed in the html:body -->
  <body xmlns="http://www.w3.org/1999/xhtml"
        style="height: 300px; overflow: auto;"/>
  
  <!-- test code goes here -->
  <script type="text/javascript"><![CDATA[
    const SPACER = /^spacer\d+/;
    const SEPARATOR = /^separator\d+/;
    const SPRING = /^spring\d+/;

    function testSet(aTb, aIDs, aResultIDs, aUseFixed) {
      // build a list of the fixed items in the order they appear on the toolbar
      var fixedSet = [];
      if (aUseFixed) {
        for (let i = 0; i < aTb.childNodes.length; i++) {
          var id = aTb.childNodes[i].id;
          if (id.indexOf("fixed") >= 0)
            fixedSet.push(id);
        }
      }

      var currentSet = aIDs.join(",");
      ok(currentSet, "setting currentSet: " + currentSet);
      aTb.currentSet = currentSet;
      var resultIDs = aResultIDs || aIDs;
      checkSet(aTb, resultIDs, fixedSet);
    }

    var checkSetCount = 0;
    function checkSet(aTb, aResultIDs, aFixedSet) {
      checkSetCount++;
      var testID = "checkSet(" + checkSetCount + ") ";

      for (let i = 0; i < aTb.childNodes.length; i++) {
        let id = aTb.childNodes[i].id;
        if (aResultIDs[i] instanceof RegExp) {
          ok(aResultIDs[i].test(id),
             testID + "correct ID " + aResultIDs[i] + " for toolbar " + aTb.id + "; got: " + id);
        }
        else if (aResultIDs[i] == "*") {
          is(id, aFixedSet.shift(), testID + "is fixed with ID " + id + " for toolbar " + aTb.id);
        }
        else {
          is(id, aResultIDs[i],
             testID + "correct ID " + aResultIDs[i] + " for toolbar " + aTb.id + 
             "****" + aResultIDs + "," + i + ",");
          // remove the item from the fixed set once found
          if (aFixedSet && id.indexOf("fixed") >= 0)
            aFixedSet.splice(aFixedSet.indexOf(id), 1);
        }
      }

      if (aFixedSet)
        is(aFixedSet.length, 0, testID + "extra fixed items for " + aTb.id);
      is(aTb.childNodes.length, aResultIDs.length,
         testID + "correct number of children for " + aTb.id);
    }

    function test_defaultSet() {
      checkSet($("tb1"), ["p1", "p2"]);
      checkSet($("tb2"), ["p4", "p3"]);
      checkSet($("tb3"), ["p5", "p6", "t31"]);
      checkSet($("tb4"), ["t41", "p7", "p8"]);
      checkSet($("tb5"), ["p9", "t51", "p10"]);
    }

    function test_currentSet(aTb) {
      ok(aTb, "have toolbar");
      var defaultSet = aTb.getAttribute("defaultset");
      var setLength = (defaultSet && defaultSet.split(",").length) || 0;
      is(setLength, aTb.childNodes.length, "correct # of children initially");

      var emptySet = [["__empty"], []];
      var testSets = [
         emptySet,
         [["p11"]],
         [["p11","p12"]],
         [["p11","p12","bogus"], ["p11","p12"]],
         [["p11"]],
         emptySet,
         [["spacer"],    [SPACER]],
         [["spring"],    [SPRING]],
         [["separator"], [SEPARATOR]],
         [["p11", "p11", "p12", "spacer", "p11"], ["p11", "p12", SPACER]],
         [["separator", "separator", "p11", "spring", "spacer"],
          [SEPARATOR, SEPARATOR, "p11", SPRING, SPACER]],
         [["separator", "spacer", "separator", "p11", "spring", "spacer", "p12", "spring"],
          [SEPARATOR, SPACER, SEPARATOR, "p11", SPRING, SPACER, "p12", SPRING]],
         emptySet
      ];

      cycleSets(aTb, testSets, emptySet, false);
    }

    function test_currentSet_nonremovable() {
      var tb = $("tb-test3");
      ok(tb, "have tb-test-3");

      // the * used in the tests below means that any fixed item can appear in that position
      var emptySet = [["__empty"], ["*", "*", "*"]];
      var testSets = [
        [["p1", "tb-fixed-1", "p2"],
         ["p1", "tb-fixed-1", "p2", "*", "*"]],
        [["p1", "tb-fixed-2", "p2"],
         ["p1", "tb-fixed-2", "p2", "*", "*"]],
        [["p1", "tb-fixed-3", "p2"],
         ["p1", "tb-fixed-3", "p2", "*", "*"]],
        emptySet,

        [["tb-fixed-1", "tb-fixed-2", "tb-fixed-3"],
         ["tb-fixed-1", "tb-fixed-2", "tb-fixed-3"]],
        [["tb-fixed-3", "tb-fixed-2", "tb-fixed-1"],
         ["tb-fixed-3", "tb-fixed-2", "tb-fixed-1"]],

        [["tb-fixed-1", "tb-fixed-2", "tb-fixed-3", "p1", "p2"],
         ["tb-fixed-1", "tb-fixed-2", "tb-fixed-3", "p1", "p2"]],

        [["tb-fixed-1", "p2", "p1"],
         ["tb-fixed-1", "p2", "p1", "*", "*"]],

        [["tb-fixed-1", "p2"],
         ["tb-fixed-1", "p2", "*", "*"]],

        [["p1", "p2"], ["p1", "p2", "*", "*", "*"]],
        [["p2", "p1"], ["p2", "p1", "*", "*", "*"]],

        [["tb-fixed-3", "spacer", "p1"],
         ["tb-fixed-3", SPACER, "p1", "*", "*"]]
      ];

      cycleSets(tb, testSets, emptySet, true);
    }

    function cycleSets(aTb, aSets, aEmptySet, aUseFixed) {
      // Since a lot of the tricky cases handled in the currentSet setter
      // depend on going from one state to another, run through the test set
      // multiple times in different orders.
      var length = aSets.length;

      for (var i = 0; i < length; i++) {
        testSet(aTb, aSets[i][0], aSets[i][1], aUseFixed);
      }
      for (var i = length - 1; i >= 0; i--) {
        testSet(aTb, aSets[i][0], aSets[i][1], aUseFixed);
      }
      for (var i = 0; i < length; i++) {
        testSet(aTb, aSets[i][0], aSets[i][1], aUseFixed);
        testSet(aTb, aSets[length - i - 1][0], aSets[length - i - 1][1], aUseFixed);
        testSet(aTb, aSets[i][0], aSets[i][1], aUseFixed);
        testSet(aTb, aSets[i][0], aSets[i][1], aUseFixed);
      }
      for (var i = 0; i < length; i++) {
        testSet(aTb, aEmptySet[0], aEmptySet[1], aUseFixed);
        testSet(aTb, aSets[i][0], aSets[i][1], aUseFixed);
      }
    }

    SimpleTest.waitForExplicitFinish();
    function startTest() {
      test_defaultSet();
      test_currentSet($("tb-test"));
      test_currentSet($("tb-test2"));
      test_currentSet_nonremovable();

      var toolbox = $("toolbox");
      var toolbars = document.getElementsByTagName("toolbar");
      for (var t = 0; t < toolbars.length; t++) {
        var toolbar = toolbars[t];
        is(toolbar.toolbox, toolbar.id == "notoolbox" ? null : toolbox,
           "toolbar " + toolbar.id + " has correct toolbox");
      }

      $("tb1").toolbox = document.documentElement;
      is($("tb1").toolbox, toolbox, "toolbox still correct after set");
      SimpleTest.finish();
    }
  ]]></script>
</window>
