/*
 * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

package sun.jvm.hotspot.ui;

import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.math.*;
import java.util.*;

/** A JScrollBar which uses BigIntegers as the representation for the
    minimum, maximum, unit increment, etc. Interaction with the
    buttons and track is accurate to unit and block increments;
    however, if the scale of the scrollbar (defined by
    getMaximumHP().subtract(getMinimumHP())) is very large, each
    interaction with the thumb will necessarily cause extremely large
    motion of the value. */

public class HighPrecisionJScrollBar extends JScrollBar {
  private BigInteger valueHP;
  private BigInteger visibleHP;
  private BigInteger minimumHP;
  private BigInteger maximumHP;
  private BigInteger unitIncrementHP;
  private BigInteger blockIncrementHP;
  private BigDecimal scaleFactor;
  private BigInteger rangeHP;
  // The underlying scrollbar runs a range from 0..BIG_RANGE-1
  private static final int BIG_RANGE = 10000;
  // Do we need to scale HP values up/down to fit in 0..BIG_RANGE-1?
  private boolean    down;
  private java.util.List changeListeners = new ArrayList();
  // Number of digits after decimal point to use when scaling between
  // high and low precision
  private static final int SCALE = 20;


  // This is a hack to allow us to differentiate between clicks on the
  // arrow and track since we can't get useful information from
  // JScrollBars' AdjustmentListener (bug in design of BasicUI
  // classes; FIXME: file RFE.)
  private static final int UNIT_INCREMENT  = 1;
  private static final int BLOCK_INCREMENT = 2;
  private static final int MINIMUM = 0;
  private static final int MAXIMUM = 65536;
  private boolean updating = false;
  private int lastValueSeen = -1;

  public HighPrecisionJScrollBar() {
    super();
    initialize();
    installListener();
  }

  public HighPrecisionJScrollBar(int orientation) {
    super(orientation);
    initialize();
    installListener();
  }

  /** value, minimum and maximum should be positive */
  public HighPrecisionJScrollBar(int orientation, BigInteger value, BigInteger minimum, BigInteger maximum) {
    super(orientation);
    initialize(value, minimum, maximum);
    installListener();
  }

  public BigInteger getValueHP() {
    return valueHP;
  }


  /** NOTE: the real value will always be set to be (value mod
      unitIncrement) == 0, subtracting off the mod of the passed value
      if necessary. */

  public void setValueHP(BigInteger value) {
    if (value.compareTo(getMaximumHP()) > 0) {
      value = getMaximumHP();
    } else if (value.compareTo(getMinimumHP()) < 0) {
      value = getMinimumHP();
    }
    valueHP = value.subtract(value.mod(unitIncrementHP));
    int lpValue = toUnderlyingRange(this.valueHP);
    if (getValueHP().add(getVisibleAmountHP()).compareTo(getMaximumHP()) >= 0 ) {
      lpValue = BIG_RANGE - getVisibleAmount();
    }
    lastValueSeen = lpValue;
    setValue(lpValue);
    fireStateChanged();
  }
  public BigInteger getMinimumHP() {
    return minimumHP;
  }

  public void setMinimumHP(BigInteger minimum) {
    setRange(minimum, maximumHP);
    updateScrollBarValues();
  }

  public BigInteger getMaximumHP() {
    return maximumHP;
  }

  public void setMaximumHP(BigInteger maximum) {
    setRange(minimumHP, maximum);
    updateScrollBarValues();
  }

  public BigInteger getVisibleAmountHP() {
    return visibleHP;
  }

  public void setVisibleAmountHP(BigInteger visibleAmount) {
    this.visibleHP = visibleAmount;
    // int lpVisAmt = toUnderlyingRange(visibleAmount);
    // Make certain that visibleAmount value that are full range come out looking like full range
    int lpVisAmt;
    if (visibleAmount.compareTo(rangeHP) < 0) {
      lpVisAmt = scaleToUnderlying(visibleAmount);
      if (lpVisAmt == 0) {
        lpVisAmt = 1;
      }
      setVisible(true);
    } else {
      lpVisAmt = BIG_RANGE;
      setVisible(false);
    }
    setVisibleAmount(lpVisAmt);
  }

  public BigInteger getBlockIncrementHP() {
    return blockIncrementHP;
  }

  public void setBlockIncrementHP(BigInteger blockIncrement) {
    this.blockIncrementHP = blockIncrement;
    // NOTE we do not forward this to the underlying scrollBar because of
    // the earlier mentioned hack.
  }

  public BigInteger getUnitIncrementHP() {
    return unitIncrementHP;
  }

  public void setUnitIncrementHP(BigInteger unitIncrement) {
    this.unitIncrementHP = unitIncrement;
    // NOTE we do not forward this to the underlying scrollBar because of
    // the earlier mentioned hack.
  }


  public void addChangeListener(ChangeListener l) {
    changeListeners.add(l);
  }

  public void removeChangeListener(ChangeListener l) {
    changeListeners.remove(l);
  }

  //----------------------------------------------------------------------
  // Programmatic access to scrollbar functionality
  // (Causes change events to be sent)

  public void scrollUpOrLeft() {
    if (updating) return;
    beginUpdate();
    setValueHP(getValueHP().subtract(getUnitIncrementHP()));
    endUpdate();
  }

  public void scrollDownOrRight() {
    if (updating) return;
    beginUpdate();
    setValueHP(getValueHP().add(getUnitIncrementHP()));
    endUpdate();
  }

  public void pageUpOrLeft() {
    if (updating) return;
    beginUpdate();
    setValueHP(getValueHP().subtract(getBlockIncrementHP()));
    endUpdate();
  }

  public void pageDownOrRight() {
    if (updating) return;
    beginUpdate();
    setValueHP(getValueHP().add(getBlockIncrementHP()));
    endUpdate();
  }

  //----------------------------------------------------------------------
  // Internals only below this point
  //

  private void beginUpdate() {
    updating = true;
  }

  private void endUpdate() {
    updating = false;
  }

  private void initialize(BigInteger value, BigInteger minimum, BigInteger maximum) {
    // Initialize the underlying scrollbar to the standard range values
    // The increments are important and are how we differentiate arrow from track events
    setMinimum(0);
    setMaximum(BIG_RANGE - 1);
    setValue(0);
    setVisibleAmount(1);
    setUnitIncrement(UNIT_INCREMENT);
    setBlockIncrement(BLOCK_INCREMENT);

    setUnitIncrementHP(new BigInteger(Integer.toString(getUnitIncrement())));
    setBlockIncrementHP(new BigInteger(Integer.toString(getBlockIncrement())));

    // Must set range and value first (it sets min/max)
    setRange(minimum, maximum);

    setVisibleAmountHP(new BigInteger(Integer.toString(getVisibleAmount())));
    setValueHP(value);
  }

  private void initialize() {
    BigInteger min = new BigInteger(Integer.toString(getMinimum()));
    BigInteger max = new BigInteger(Integer.toString(getMaximum()));
    initialize(min, min, max);
  }

  private void setRange(BigInteger minimum, BigInteger maximum) {
    if (minimum.compareTo(maximum) > 0 ) {
      throw new RuntimeException("Bad scrollbar range " + minimum + " > " + maximum);
    }
    minimumHP = minimum;
    maximumHP = maximum;
    rangeHP = maximum.subtract(minimum).add(BigInteger.ONE);
    BigInteger range2 = new BigInteger(Integer.toString(BIG_RANGE));
    if (rangeHP.compareTo(range2) >= 0 ) {
      down = true;
      scaleFactor = new BigDecimal(rangeHP, SCALE).divide(new BigDecimal(range2, SCALE), BigDecimal.ROUND_DOWN).max(new BigDecimal(BigInteger.ONE));
    } else {
      down = false;
      scaleFactor = new BigDecimal(range2, SCALE).divide(new BigDecimal(rangeHP, SCALE), BigDecimal.ROUND_DOWN).max(new BigDecimal(BigInteger.ONE));
    }
    // FIXME: should put in original scaling algorithm (shifting by
    // number of bits) as alternative when scale between low and high
    // precision is very large
  }

  // A range update is complete. Rescale our computed values and
  // inform the underlying scrollBar as needed.
  private void updateScrollBarValues() {
    setValueHP(getValueHP());
    setVisibleAmountHP(getVisibleAmountHP());
    setBlockIncrementHP(getBlockIncrementHP());
    setUnitIncrementHP(getUnitIncrementHP());
  }

  private BigDecimal getScaleFactor() {
    return scaleFactor;
  }


  // Value scaling routines
  private BigInteger scaleToHP(int i) {
    BigDecimal ib = new BigDecimal(Integer.toString(i));
    if (down) return ib.multiply(getScaleFactor()).toBigInteger();
    else return ib.divide(getScaleFactor(), BigDecimal.ROUND_DOWN).toBigInteger();
  }

  private int scaleToUnderlying(BigInteger i) {
    BigDecimal d = new BigDecimal(i);
    if (down) return d.divide(getScaleFactor(), BigDecimal.ROUND_DOWN).intValue();
    else return d.multiply(getScaleFactor()).intValue();
  }

  // Range scaling routines
  private BigInteger toHPRange(int i) {
    return scaleToHP(i).add(minimumHP);
    // return ib.shiftLeft(Math.max(2, maximumHP.bitLength() - 33));
  }

  private int toUnderlyingRange(BigInteger i) {
    return scaleToUnderlying(i.subtract(minimumHP));
    // return i.shiftRight(Math.max(2, maximumHP.bitLength() - 33)).intValue();
  }

  private void installListener() {
    super.addAdjustmentListener(new AdjustmentListener() {
        public void adjustmentValueChanged(AdjustmentEvent e) {
          if (updating) {
            return;
          }
          beginUpdate();
          switch (e.getAdjustmentType()) {
          case AdjustmentEvent.TRACK:
            int val = e.getValue();
            int diff = val - lastValueSeen;
            int absDiff = Math.abs(diff);
            //            System.err.println("diff: " + diff + " absDiff: " + absDiff);
            if (absDiff == UNIT_INCREMENT) {
              if (diff > 0) {
                //                System.err.println("case 1");
                setValueHP(getValueHP().add(getUnitIncrementHP()));
              } else {
                //                System.err.println("case 2");
                setValueHP(getValueHP().subtract(getUnitIncrementHP()));
              }
            } else if (absDiff == BLOCK_INCREMENT) {
              if (diff > 0) {
                //                System.err.println("case 3");
                setValueHP(getValueHP().add(getBlockIncrementHP()));
              } else {
                //                System.err.println("case 4");
                setValueHP(getValueHP().subtract(getBlockIncrementHP()));
              }
            } else {
              //              System.err.println("case 5");
              // FIXME: seem to be getting spurious update events,
              // with diff = 0, upon mouse down/up on the track
              if (absDiff != 0) {
                // Convert low-precision value to high precision
                // (note we lose the low bits)
                BigInteger i = null;
                if (e.getValue() == getMinimum()) {
                  i = getMinimumHP();
                } else if (e.getValue() >= getMaximum() - 1) {
                  i = getMaximumHP();
                } else {
                  i = toHPRange(e.getValue());
                }
                setValueHP(i);
              }
            }
            break;
          default:
            // Should not reach here, but leaving it a no-op in case
            // we later get the other events (should revisit code in
            // that case)
            break;
          }
          endUpdate();
        }
      });
  }

  private void fireStateChanged() {
    ChangeEvent e = null;
    for (Iterator iter = changeListeners.iterator(); iter.hasNext(); ) {
      ChangeListener l = (ChangeListener) iter.next();
      if (e == null) {
        e = new ChangeEvent(this);
      }
      l.stateChanged(e);
    }
  }

  public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.setSize(300, 300);
    // 32-bit version
    /*
    HighPrecisionJScrollBar hpsb =
      new HighPrecisionJScrollBar(
        JScrollBar.VERTICAL,
        new BigInteger(1, new byte[] {
          (byte) 0x80, (byte) 0x00, (byte) 0x00, (byte) 0x00}),
        new BigInteger(1, new byte[] {
          (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00}),
        new BigInteger(1, new byte[] {
          (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF}));
    hpsb.setUnitIncrementHP(new BigInteger(1, new byte[] {
      (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01}));
    hpsb.setBlockIncrementHP(new BigInteger(1, new byte[] {
      (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x10}));
    */

    // 64-bit version
    HighPrecisionJScrollBar hpsb =
      new HighPrecisionJScrollBar(
        JScrollBar.VERTICAL,
        new BigInteger(1, new byte[] {
          (byte) 0x80, (byte) 0x00, (byte) 0x00, (byte) 0x00,
          (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00}),
        new BigInteger(1, new byte[] {
          (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
          (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00}),
        new BigInteger(1, new byte[] {
          (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
          (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF}));
    hpsb.setUnitIncrementHP(new BigInteger(1, new byte[] {
      (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
      (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01}));
    hpsb.setBlockIncrementHP(new BigInteger(1, new byte[] {
      (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
      (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x10}));
    hpsb.addChangeListener(new ChangeListener() {
        public void stateChanged(ChangeEvent e) {
          HighPrecisionJScrollBar h = (HighPrecisionJScrollBar) e.getSource();
          System.out.println("New value = 0x" + h.getValueHP().toString(16));
        }
      });
    frame.getContentPane().add(hpsb);
    frame.setVisible(true);
  }

}
