/*
 * $Id: RandomTextButton.java 4531 2008-11-25 15:42:26Z uckelman $
 *
 * Copyright (c) 2004 by Michael Blumoehr
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License (LGPL) as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, copies are available
 * at http://www.opensource.org.
 */
package VASSAL.build.module;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;
import VASSAL.build.GameModule;
import VASSAL.build.module.documentation.HelpFile;
import VASSAL.command.Command;
import VASSAL.command.NullCommand;
import VASSAL.configure.AutoConfigurer;
import VASSAL.configure.ConfigurerWindow;
import VASSAL.configure.StringArrayConfigurer;
import VASSAL.configure.VisibilityCondition;
import VASSAL.tools.LaunchButton;

/**
 * @author Michael Blumoehr
 *
 * This component places a button into the controls window toolbar.
 * Pressing the button generates random numbers or strings and displays the
 * result in the Chatter
 */
// TODO Expose result as a property
public class RandomTextButton extends DiceButton {
  protected String[] m_faces;               // array with dice faces
  protected boolean isNumeric;

  public static final String FACES = "faces"; //$NON-NLS-1$
  public static final String NUMERIC = "numeric"; //$NON-NLS-1$

  public RandomTextButton() {
    super();
    ActionListener ranAction = new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        if (promptAlways) {
          promptAlways = false; // Show the usu
          // Remove label, hotkey, and prompt controls
          AutoConfigurer ac = (AutoConfigurer) getConfigurer();
          ConfigurerWindow w = new ConfigurerWindow(ac, true);
          ac.getConfigurer(NAME).getControls().setVisible(false);
          ac.getConfigurer(BUTTON_TEXT).getControls().setVisible(false);
          ac.getConfigurer(TOOLTIP).getControls().setVisible(false);
          ac.getConfigurer(ICON).getControls().setVisible(false);
          ac.getConfigurer(HOTKEY).getControls().setVisible(false);
          ac.getConfigurer(PROMPT_ALWAYS).getControls().setVisible(false);
          ac.getConfigurer(REPORT_FORMAT).getControls().setVisible(false);
          ac.getConfigurer(REPORT_TOTAL).getControls().setVisible(false);
          ac.getConfigurer(FACES).getControls().setVisible(false);
          ac.getConfigurer(NUMERIC).getControls().setVisible(false);
          w.pack();
          w.setVisible(true);
          ac.getConfigurer(NAME).getControls().setVisible(true);
          ac.getConfigurer(BUTTON_TEXT).getControls().setVisible(true);
          ac.getConfigurer(TOOLTIP).getControls().setVisible(true);
          ac.getConfigurer(ICON).getControls().setVisible(true);
          ac.getConfigurer(HOTKEY).getControls().setVisible(true);
          ac.getConfigurer(PROMPT_ALWAYS).getControls().setVisible(true);
          ac.getConfigurer(REPORT_FORMAT).getControls().setVisible(true);
          ac.getConfigurer(REPORT_TOTAL).getControls().setVisible(true);
          ac.getConfigurer(FACES).getControls().setVisible(true);
          ac.getConfigurer(NUMERIC).getControls().setVisible(true);
          if (! w.isCancelled()) {
            DR();
          }
          promptAlways = true;
        }
        else {
          DR();
        }
      }
    };
    launch = new LaunchButton(null, TOOLTIP, BUTTON_TEXT, HOTKEY, ICON, ranAction);
    setAttributeTranslatable(FACES, true);
  }
  
  public static String getConfigureTypeName() {
    return "Random Text Button";
  }

  /**
   * Forwards the result of the roll to the {@link Chatter#send}
   * method of the {@link Chatter} of the {@link GameModule}.  Format is
   * prefix+[comma-separated roll list]+suffix */
  protected void DR() {
    final StringBuilder result = new StringBuilder();
    int total = addToTotal;
    for (int i = 0; i < nDice; ++i) {
      int roll = (int) (ran.nextFloat() * nSides + 1);

      // take the face value from user defined faces
      if (isNumeric) {
        roll = Integer.parseInt(m_faces[roll - 1]) + plus;
      }

      // no totals if text output
      if (reportTotal && isNumeric) {
        total += roll;
      }
      else {
        if (!isNumeric)
          result.append(m_faces[roll - 1]);
        else
          result.append(roll);
        if (i < nDice - 1)
          result.append(","); //$NON-NLS-1$
      }
    }

    // totals only if no text output
    if (reportTotal && isNumeric)
      result.append(total);

    String report = formatResult(result.toString());
    Command c = report.length() == 0 ? new NullCommand() : new Chatter.DisplayText(GameModule.getGameModule().getChatter(),report);
    c.execute();
    c.append(property.setPropertyValue(result.toString()));
    GameModule.getGameModule().sendAndLog(c);

  }

  public VisibilityCondition getAttributeVisibility(String name) {
    if (REPORT_TOTAL.equals(name)
        || PLUS.equals(name)
        || ADD_TO_TOTAL.equals(name)) {
      return new VisibilityCondition() {
        public boolean shouldBeVisible() {
          return isNumeric;
        }
      };
    }
    else {
      return super.getAttributeVisibility(name);
    }
  }


  /**
   * The additional Attributes of a RandomTextButton are:
   *
   * <code>FACES</code> Text of the dice faces
   *                    must be integer if USE_FACES=NUMERIC

   * <code>NUMERIC</code>   If true, then face text must be an integer,
   *  and reportTotal is enabled
   */
  public String[] getAttributeNames() {
    ArrayList<String> l =
      new ArrayList<String>(Arrays.asList(super.getAttributeNames()));
    l.remove(N_SIDES);
    l.add(FACES);
    l.add(NUMERIC);
    return l.toArray(new String[l.size()]);
  }

  public String[] getAttributeDescriptions() {
    ArrayList<String> l =
      new ArrayList<String>(Arrays.asList(super.getAttributeDescriptions()));
    ArrayList<String> names =
      new ArrayList<String>(Arrays.asList(super.getAttributeNames()));
    l.remove(names.indexOf(N_SIDES));
    l.add("Faces");
    l.add("Faces have numeric values?");
    return l.toArray(new String[l.size()]);
  }

  public Class<?>[] getAttributeTypes() {
    ArrayList<Class<?>> l =
      new ArrayList<Class<?>>(Arrays.asList(super.getAttributeTypes()));
    ArrayList<String> names =
      new ArrayList<String>(Arrays.asList(super.getAttributeNames()));
    l.remove(names.indexOf(N_SIDES));
    l.add(String[].class);
    l.add(Boolean.class);
    return l.toArray(new Class<?>[names.size()]);
  }

  public void setAttribute(String key, Object value) {
    if (NUMERIC.equals(key)) {
      isNumeric = Boolean.TRUE.equals(value) || "true".equals(value); //$NON-NLS-1$
    }
    else if (FACES.equals(key)) {
      if (value instanceof String) {
        value = StringArrayConfigurer.stringToArray((String) value);
      }
      m_faces = (String[]) value;
      nSides = m_faces.length;
    }
    else {
      super.setAttribute(key, value);
    }
  }

  public String getAttributeValueString(String key) {
    if (NUMERIC.equals(key)) {
      return String.valueOf(isNumeric);
    }
    else if (FACES.equals(key)) {
      return StringArrayConfigurer.arrayToString(m_faces);
    }
    else {
      return super.getAttributeValueString(key);
    }
  }

  public HelpFile getHelpFile() {
    return HelpFile.getReferenceManualPage("GameModule.htm", "RandomTextButton"); //$NON-NLS-1$ //$NON-NLS-2$
  }


}
