package net.mmss.swing.group;

import java.awt.event.*;
import java.io.Serializable;
import javax.swing.*;
import java.util.*;

public class JCheckBoxGroup extends JRadioButtonGroup implements Serializable {

  //Vector botton field inherited from JRadioButtonGroup
  ArrayList selection = new ArrayList();

  //the number of check boxes could be selected at one time.
  int selectableCount;

  public static final int NONE = 0; //no box will be uncheck
  //user entries will be neglected if selectable count number is reached
  public static final int FIRST = 1; //first checked box will be unchecked
  public static final int LAST = 2; //last checked box will be unchecked

  //set which checked box to uncheck if another checked
  private int replaceAt;

  public JCheckBoxGroup() {
    selectableCount = 1;
    replaceAt = LAST;
  }

  public JCheckBoxGroup(int selectableCount) {
    this();
    this.selectableCount = selectableCount;
  }

  public JCheckBoxGroup(int selectableCount, int replacement) {
    this.selectableCount = selectableCount;
    replaceAt = replacement;
  }

  public void add(AbstractButton b) {
    if (b == null) {
      return;
    }
    buttons.addElement(b);

    if (b.isSelected()) {
      if (getSelectedCount() < selectableCount) {
        selection.add(b.getModel());
      } else {
        b.setSelected(false);
      }
    }

    b.getModel().setGroup(this);
  }

  public void remove(AbstractButton b) {
    if (b == null) {
      return;
    }
    buttons.removeElement(b);
    if (selection.contains(b)) {
      selection.remove(b.getModel());
    }
    b.getModel().setGroup(null);
  }

  public void setSelected(ButtonModel m, boolean b) {
    int mIndex = -1;
    if (selection != null) {
      mIndex = selection.indexOf(m);
    }
    if (!b && m != null && mIndex >= 0) {
      ButtonModel oldSelection = (ButtonModel)selection.get(mIndex);
      selection.remove(mIndex);
      if (oldSelection != null) {
        oldSelection.setSelected(false);
      }
      m.setSelected(false);
      return;
    }
    if (b && m != null && mIndex == -1) {
      if (getSelectedCount() == selectableCount) {
        ButtonModel oldSelection = null;
        switch (replaceAt) {
          case FIRST:
            oldSelection = (ButtonModel)selection.get(0);
            selection.remove(0);
            break;
          case LAST:
            oldSelection = (ButtonModel)selection.get(getSelectedCount()-1);
            selection.remove(getSelectedCount()-1);
            break;
          default:
            return;
        }
        if (oldSelection != null) {
          oldSelection.setSelected(false);
        }
      }
      selection.add(m);
      m.setSelected(true);
    }
  }

  public void deselectAll() {
    List oldSelection = selection;
    selection.clear();
    if (oldSelection != null) {
      Iterator it = oldSelection.iterator();
      while (it.hasNext()) {
        ((ButtonModel)it.next()).setSelected(false);
      }
    }
  }

  public int getSelectedCount() {
    if (selection == null)
      return 0;
    else
      return selection.size();
  }

  public boolean isSelected(ButtonModel m) {
    return selection.contains(m);
  }

  public int getSelectableCount() {
    return selectableCount;
  }

  public void setSelectableCount(int selectableCount) {
    this.selectableCount = selectableCount;
  }

  public ButtonModel getSelection() {
    return getSelection(0);
  }

  public ButtonModel getSelection(int index) {
    return (ButtonModel)selection.get(index);
  }

  public void replaceAt(int replacement) {
    replaceAt = replacement;
  }
}
