/**
   * Gets background color for cell for row ic. Override it if you want to change the color from the
   * default.
   */
  public Color getBackgroundColorOfCell(int it, boolean selected) {
    if (observedStates == null) {
      doCalcs();
      if (observedStates == null) return null;
    }
    if (observedStates.getParentData() != null) {
      captureCharacterDataFromObservedStates();

      Associable tInfo = data.getTaxaInfo(false);
      NameReference genBankColor = NameReference.getNameReference("genbankcolor");
      Object obj = tInfo.getAssociatedObject(genBankColor, it); // not saved to file
      if (obj instanceof Color) return (Color) obj;
    }
    if (bits == null || it < 0 || it > bits.getSize()) return null;
    String note = getNote(it);
    if (selected) {
      if (bits.isBitOn(it)) return ColorDistribution.darkGreen;
      else return ColorDistribution.darkRed;
    } else if (bits.isBitOn(it)) {
      if (StringUtil.blank(note)) return ColorDistribution.veryLightGreen;
      if (!(note.equalsIgnoreCase("x"))) return ColorDistribution.lightGreenYellowish;
      return ColorDistribution.lightGreenYellow;
    } else {
      if (StringUtil.blank(note)) return ColorDistribution.brown;
      if (!(note.equalsIgnoreCase("x"))) {
        return Color.red;
      }
      return ColorDistribution.lightRed;
    }
  }
/* ======================================================================== */
public class ColorTaxon extends TaxaListAssistantI {
  Taxa taxa;
  MesquiteTable table;
  TableTool tool;
  long currentColor = ColorDistribution.numberOfRed;
  String colorString = "Color Red";
  long savedColor = currentColor;
  MesquiteBoolean removeColor;
  NameReference colorNameRef = NameReference.getNameReference("color");

  public String getName() {
    return "Color Taxa";
  }

  public String getExplanation() {
    return "Provides paintbrush to color taxon names.";
  }

  /*.................................................................................................................*/
  public int getVersionOfFirstRelease() {
    return 260;
  }
  /*.................................................................................................................*/
  public boolean startJob(String arguments, Object condition, boolean hiredByName) {
    MesquiteSubmenuSpec mss =
        addSubmenu(
            null,
            "Cell paint color",
            makeCommand("setColor", this),
            ColorDistribution.standardColorNames);
    removeColor = new MesquiteBoolean(false);
    addCheckMenuItem(null, "Remove color", makeCommand("removeColor", this), removeColor);
    addMenuItem(null, "Remove all color", makeCommand("removeAllColor", this));
    MesquiteSubmenuSpec mss2 =
        addSubmenu(
            null,
            "Set Color of Selected",
            makeCommand("setColorSelected", this),
            ColorDistribution.standardColorNames);
    // addMenuItem(null, "-", null);
    // addMenuItem(null, "Color Selected", makeCommand("colorSelected",  this));
    setUseMenubar(false); // menu available by touching button
    return true;
  }

  private void removeColor(int it, boolean notify) {
    setColor(it, MesquiteLong.unassigned);
    if (notify) table.redrawCell(-1, it);
  }

  private void removeAllColor(boolean notify) {
    for (int it = 0; it < taxa.getNumTaxa(); it++) setColor(it, MesquiteLong.unassigned);
    if (notify) table.repaintAll();
  }

  private void setColor(int it, long c) {
    if (it < 0) return;
    taxa.setAssociatedLong(colorNameRef, it, c);
    table.redrawCell(-1, it);
  }
  /*.................................................................................................................*/
  public Snapshot getSnapshot(MesquiteFile file) {
    Snapshot temp = new Snapshot();
    temp.addLine(
        "setColor "
            + ColorDistribution.getStandardColorName(
                ColorDistribution.getStandardColor((int) currentColor)));
    temp.addLine("removeColor " + removeColor.toOffOnString());
    return temp;
  }
  /*.................................................................................................................*/
  /**
   * A request for the MesquiteModule to perform a command. It is passed two strings, the name of
   * the command and the arguments. This should be overridden by any module that wants to respond to
   * a command.
   */
  public Object doCommand(String commandName, String arguments, CommandChecker checker) {
    if (checker.compare(MesquiteModule.class, null, null, commandName, "paint")) {
      MesquiteInteger io = new MesquiteInteger(0);
      int column = MesquiteInteger.fromString(arguments, io);
      int row = MesquiteInteger.fromString(arguments, io);
      if (MesquiteInteger.isCombinable(row)) {
        if (!MesquiteLong.isCombinable(currentColor)) removeColor(row, true);
        else setColor(row, (int) currentColor);
      }
    } else if (checker.compare(
        this.getClass(),
        "Sets the color to be used to paint cells",
        "[name of color]",
        commandName,
        "setColor")) {
      int bc = ColorDistribution.standardColorNames.indexOf(parser.getFirstToken(arguments));
      if (bc >= 0 && MesquiteLong.isCombinable(bc)) {
        removeColor.setValue(false);
        currentColor = bc;
        savedColor = bc;
        colorString = "Color " + ColorDistribution.standardColorNames.getValue(bc);
      }
    } else if (checker.compare(
        this.getClass(),
        "Sets the color of selected taxa",
        "[name of color]",
        commandName,
        "setColorSelected")) {
      int bc = ColorDistribution.standardColorNames.indexOf(parser.getFirstToken(arguments));
      if (bc >= 0 && MesquiteLong.isCombinable(bc)) {
        for (int it = 0; it < taxa.getNumTaxa(); it++) if (taxa.getSelected(it)) setColor(it, bc);
      }
    } else if (checker.compare(
        this.getClass(), "Removes color from all the cells", null, commandName, "removeAllColor")) {
      removeAllColor(true);
    } else if (checker.compare(
        this.getClass(),
        "Sets the paint brush so that it removes colors from any cells touched",
        null,
        commandName,
        "removeColor")) {
      if (StringUtil.blank(arguments)) removeColor.setValue(!removeColor.getValue());
      else removeColor.toggleValue(parser.getFirstToken(arguments));

      if (removeColor.getValue()) {
        colorString = "Remove color";
        currentColor = MesquiteLong.unassigned;
      } else {
        colorString = "Color " + ColorDistribution.standardColorNames.getValue((int) currentColor);
        currentColor = savedColor;
      }
    } else return super.doCommand(commandName, arguments, checker);
    return null;
  }
  /*.................................................................................................................*/
  public boolean isSubstantive() {
    return false;
  }
  /*.................................................................................................................*/
  public void setTableAndTaxa(MesquiteTable table, Taxa taxa) {
    this.table = table;
    this.taxa = taxa;
    if (containerOfModule() instanceof ListWindow && tool == null) {
      String sortExplanation = "Assigns colors to taxa. ";
      tool =
          new TableTool(
              this,
              "sort",
              getPath(),
              "color.gif",
              0,
              0,
              "Color taxon",
              sortExplanation,
              MesquiteModule.makeCommand("paint", this),
              null,
              null);
      tool.setWorksOnRowNames(true);
      ((ListWindow) containerOfModule()).addTool(tool);
      tool.setPopUpOwner(this);
    }
  }
}