/*
 * Copyright 2003-2006 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package sun.awt.X11;

import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.AdjustmentEvent;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import sun.awt.motif.X11FontMetrics;
import java.util.logging.*;

// FIXME: implement multi-select
/*
 * Class to paint a list of items, possibly with scrollbars
 * This class paints all items with the same font
 * For now, this class manages the list of items and painting thereof, but not
 * posting of Item or ActionEvents
 */
public class ListHelper implements XScrollbarClient {
    private static final Logger log = Logger.getLogger("sun.awt.X11.ListHelper");

    private final int FOCUS_INSET = 1;

    private final int BORDER_WIDTH; // Width of border drawn around the list
                                    // of items
    private final int ITEM_MARGIN;  // Margin between the border of the list
                                    // of items and and item's bg, and between
                                    // items
    private final int TEXT_SPACE;   // Space between the edge of an item and
                                    // the text

    private final int SCROLLBAR_WIDTH;  // Width of a scrollbar

    private java.util.List items;        // List of items

    // TODO: maybe this would be better as a simple int[]
    private java.util.List selected;     // List of selected items
    private boolean multiSelect;         // Can multiple items be selected
                                         // at once?
    private int focusedIndex;

    private int maxVisItems;             // # items visible without a vsb
    private XVerticalScrollbar vsb;      // null if unsupported
    private boolean vsbVis;
    private XHorizontalScrollbar hsb;    // null if unsupported
    private boolean hsbVis;

    private Font font;
    private FontMetrics fm;

    private XWindow peer;   // So far, only needed for painting
                            // on notifyValue()
    private Color[] colors; // Passed in for painting on notifyValue()

    // Holds the true if mouse is dragging outside of the area of the list
    // The flag is used at the moment of the dragging and releasing mouse
    // See 6243382 for more information
    boolean mouseDraggedOutVertically = false;
    private volatile boolean vsbVisibilityChanged = false;

    /*
     * Comment
     */
    public ListHelper(XWindow peer,
                      Color[] colors,
                      int initialSize,
                      boolean multiSelect,
                      boolean scrollVert,
                      boolean scrollHoriz,
                      Font font,
                      int maxVisItems,
                      int SPACE,
                      int MARGIN,
                      int BORDER,
                      int SCROLLBAR) {
        this.peer = peer;
        this.colors = colors;
        this.multiSelect = multiSelect;
        items = new ArrayList(initialSize);
        selected = new ArrayList(1);
        selected.add(Integer.valueOf(-1));

        this.maxVisItems = maxVisItems;
        if (scrollVert) {
            vsb = new XVerticalScrollbar(this);
            vsb.setValues(0, 0, 0, 0, 1, maxVisItems - 1);
        }
        if (scrollHoriz) {
            hsb = new XHorizontalScrollbar(this);
            hsb.setValues(0, 0, 0, 0, 1, 1);
        }

        setFont(font);
        TEXT_SPACE = SPACE;
        ITEM_MARGIN = MARGIN;
        BORDER_WIDTH = BORDER;
        SCROLLBAR_WIDTH = SCROLLBAR;
    }

    public Component getEventSource() {
        return peer.getEventSource();
    }

    /**********************************************************************/
    /* List management methods                                            */
    /**********************************************************************/

    public void add(String item) {
        items.add(item);
        updateScrollbars();
    }

    public void add(String item, int index) {
        items.add(index, item);
        updateScrollbars();
    }

    public void remove(String item) {
        // FIXME: need to clean up select list, too?
        items.remove(item);
        updateScrollbars();
        // Is vsb visible now?
    }

    public void remove(int index) {
        // FIXME: need to clean up select list, too?
        items.remove(index);
        updateScrollbars();
        // Is vsb visible now?
    }

    public void removeAll() {
        items.removeAll(items);
        updateScrollbars();
    }

    public void setMultiSelect(boolean ms) {
        multiSelect = ms;
    }

    /*
     * docs.....definitely docs
     * merely keeps internal track of which items are selected for painting
     * dealing with target Components happens elsewhere
     */
    public void select(int index) {
        if (index > getItemCount() - 1) {
            index = (isEmpty() ? -1 : 0);
        }
        if (multiSelect) {
            assert false : "Implement ListHelper.select() for multiselect";
        }
        else if (getSelectedIndex() != index) {
            selected.remove(0);
            selected.add(Integer.valueOf(index));
            makeVisible(index);
        }
    }

    /* docs */
    public void deselect(int index) {
        assert(false);
    }

    /* docs */
    /* if called for multiselect, return -1 */
    public int getSelectedIndex() {
        if (!multiSelect) {
            Integer val = (Integer)selected.get(0);
            return val.intValue();
        }
        return -1;
    }

    int[] getSelectedIndexes() { assert(false); return null;}

    /*
     * A getter method for XChoicePeer.
     * Returns vsbVisiblityChanged value and sets it to false.
     */
    public boolean checkVsbVisibilityChangedAndReset(){
        boolean returnVal = vsbVisibilityChanged;
        vsbVisibilityChanged = false;
        return returnVal;
    }

    public boolean isEmpty() {
        return items.isEmpty();
    }

    public int getItemCount() {
        return items.size();
    }

    public String getItem(int index) {
        return (String) items.get(index);
    }

    /**********************************************************************/
    /* GUI-related methods                                                */
    /**********************************************************************/

    public void setFocusedIndex(int index) {
        focusedIndex = index;
    }

    public boolean isFocusedIndex(int index) {
        return index == focusedIndex;
    }

    public void setFont(Font newFont) {
        if (newFont != font) {
            font = newFont;
            fm = Toolkit.getDefaultToolkit().getFontMetrics(font);
            // Also cache stuff like fontHeight?
        }
    }

    /*
     * Returns width of the text of the longest item
     */
    public int getMaxItemWidth() {
        int m = 0;
        int end = getItemCount();
        for(int i = 0 ; i < end ; i++) {
            int l = fm.stringWidth(getItem(i));
            m = Math.max(m, l);
        }
        return m;
    }

    /*
     * Height of an item (this doesn't include ITEM_MARGIN)
     */
    int getItemHeight() {
        return fm.getHeight() + (2*TEXT_SPACE);
    }

    public int y2index(int y) {
        if (log.isLoggable(Level.FINE)) {
            log.fine("y=" + y +", firstIdx=" + firstDisplayedIndex() +", itemHeight=" + getItemHeight()
                     + ",item_margin=" + ITEM_MARGIN);
        }
        // See 6243382 for more information
        int newIdx = firstDisplayedIndex() + ((y - 2*ITEM_MARGIN) / (getItemHeight() + 2*ITEM_MARGIN));
        return newIdx;
    }

    /* write these
    int index2y(int);
    public int numItemsDisplayed() {}
    */

    public int firstDisplayedIndex() {
        if (vsbVis) {
            return vsb.getValue();
        }
        return 0;
    }

    public int lastDisplayedIndex() {
        // FIXME: need to account for horiz scroll bar
        if (hsbVis) {
            assert false : "Implement for horiz scroll bar";
        }

        return vsbVis ? vsb.getValue() + maxVisItems - 1: getItemCount() - 1;
    }

    /*
     * If the given index is not visible in the List, scroll so that it is.
     */
    public void makeVisible(int index) {
        if (vsbVis) {
            if (index < firstDisplayedIndex()) {
                vsb.setValue(index);
            }
            else if (index > lastDisplayedIndex()) {
                vsb.setValue(index - maxVisItems + 1);
            }
        }
    }

    // FIXME: multi-select needs separate focused index
    public void up() {
        int curIdx = getSelectedIndex();
        int numItems = getItemCount();
        int newIdx;

        assert curIdx >= 0;

        if (curIdx == 0) {
            newIdx = numItems - 1;
        }
        else {
            newIdx = --curIdx;
        }
        // focus(newIdx);
        select(newIdx);
    }

    public void down() {
        int newIdx = (getSelectedIndex() + 1) % getItemCount();
        select(newIdx);
    }

    public void pageUp() {
        // FIXME: for multi-select, move the focused item, not the selected item
        if (vsbVis && firstDisplayedIndex() > 0) {
            if (multiSelect) {
                assert false : "Implement pageUp() for multiSelect";
            }
            else {
                int selectionOffset = getSelectedIndex() - firstDisplayedIndex();
                // the vsb does bounds checking
                int newIdx = firstDisplayedIndex() - vsb.getBlockIncrement();
                vsb.setValue(newIdx);
                select(firstDisplayedIndex() + selectionOffset);
            }
        }
    }
    public void pageDown() {
        if (vsbVis && lastDisplayedIndex() < getItemCount() - 1) {
            if (multiSelect) {
                assert false : "Implement pageDown() for multiSelect";
            }
            else {
                int selectionOffset = getSelectedIndex() - firstDisplayedIndex();
                // the vsb does bounds checking
                int newIdx = lastDisplayedIndex();
                vsb.setValue(newIdx);
                select(firstDisplayedIndex() + selectionOffset);
            }
        }
    }
    public void home() {}
    public void end() {}


    public boolean isVSBVisible() { return vsbVis; }
    public boolean isHSBVisible() { return hsbVis; }

    public XVerticalScrollbar getVSB() { return vsb; }
    public XHorizontalScrollbar getHSB() { return hsb; }

    public boolean isInVertSB(Rectangle bounds, int x, int y) {
        if (vsbVis) {
            assert vsb != null : "Vert scrollbar is visible, yet is null?";
            int sbHeight = hsbVis ? bounds.height - SCROLLBAR_WIDTH : bounds.height;
            return (x <= bounds.width) &&
                   (x >= bounds.width - SCROLLBAR_WIDTH) &&
                   (y >= 0) &&
                   (y <= sbHeight);
        }
        return false;
    }

    public boolean isInHorizSB(Rectangle bounds, int x, int y) {
        if (hsbVis) {
            assert hsb != null : "Horiz scrollbar is visible, yet is null?";

            int sbWidth = vsbVis ? bounds.width - SCROLLBAR_WIDTH : bounds.width;
            return (x <= sbWidth) &&
                   (x >= 0) &&
                   (y >= bounds.height - SCROLLBAR_WIDTH) &&
                   (y <= bounds.height);
        }
        return false;
    }

    public void handleVSBEvent(MouseEvent e, Rectangle bounds, int x, int y) {
        int sbHeight = hsbVis ? bounds.height - SCROLLBAR_WIDTH : bounds.height;

        vsb.handleMouseEvent(e.getID(),
                             e.getModifiers(),
                             x - (bounds.width - SCROLLBAR_WIDTH),
                             y);
    }

    /*
     * Called when items are added/removed.
     * Update whether the scrollbar is visible or not, scrollbar values
     */
    void updateScrollbars() {
        boolean oldVsbVis = vsbVis;
        vsbVis = vsb != null && items.size() > maxVisItems;
        if (vsbVis) {
            vsb.setValues(vsb.getValue(), getNumItemsDisplayed(),
                          vsb.getMinimum(), items.size());
        }

        // 6405689. If Vert Scrollbar gets disappeared from the dropdown menu we should repaint whole dropdown even if
        // no actual resize gets invoked. This is needed because some painting artifacts remained between dropdown items
        // but draw3DRect doesn't clear the area inside. Instead it just paints lines as borders.
        vsbVisibilityChanged = (vsbVis != oldVsbVis);
        // FIXME: check if added item makes a hsb necessary (if supported, that of course)
    }

    public int getNumItemsDisplayed() {
        return items.size() > maxVisItems ? maxVisItems : items.size();
    }

    public void repaintScrollbarRequest(XScrollbar sb) {
        Graphics g = peer.getGraphics();
        Rectangle bounds = peer.getBounds();
        if ((sb == vsb) && vsbVis) {
            paintVSB(g, XComponentPeer.getSystemColors(), bounds);
        }
        else if ((sb == hsb) && hsbVis) {
            paintHSB(g, XComponentPeer.getSystemColors(), bounds);
        }
        g.dispose();
    }

    public void notifyValue(XScrollbar obj, int type, int v, boolean isAdjusting) {
        if (obj == vsb) {
            int oldScrollValue = vsb.getValue();
            vsb.setValue(v);
            boolean needRepaint = (oldScrollValue != vsb.getValue());
            // See 6243382 for more information
            if (mouseDraggedOutVertically){
                int oldItemValue = getSelectedIndex();
                int newItemValue = getSelectedIndex() + v - oldScrollValue;
                select(newItemValue);
                needRepaint = needRepaint || (getSelectedIndex() != oldItemValue);
            }

            // FIXME: how are we going to paint!?
            Graphics g = peer.getGraphics();
            Rectangle bounds = peer.getBounds();
            int first = v;
            int last = Math.min(getItemCount() - 1,
                                v + maxVisItems);
            if (needRepaint) {
                paintItems(g, colors, bounds, first, last);
            }
            g.dispose();

        }
        else if ((XHorizontalScrollbar)obj == hsb) {
            hsb.setValue(v);
            // FIXME: how are we going to paint!?
        }
    }

    public void updateColors(Color[] newColors) {
        colors = newColors;
    }

    /*
    public void paintItems(Graphics g,
                           Color[] colors,
                           Rectangle bounds,
                           Font font,
                           int first,
                           int last,
                           XVerticalScrollbar vsb,
                           XHorizontalScrollbar hsb) {
    */
    public void paintItems(Graphics g,
                           Color[] colors,
                           Rectangle bounds) {
        // paint border
        // paint items
        // paint scrollbars
        // paint focus?

    }
    public void paintAllItems(Graphics g,
                           Color[] colors,
                           Rectangle bounds) {
        paintItems(g, colors, bounds,
                   firstDisplayedIndex(), lastDisplayedIndex());
    }
    public void paintItems(Graphics g,
                           Color[] colors,
                           Rectangle bounds,
                           int first,
                           int last) {
        peer.flush();
        int x = BORDER_WIDTH + ITEM_MARGIN;
        int width = bounds.width - 2*ITEM_MARGIN - 2*BORDER_WIDTH - (vsbVis ? SCROLLBAR_WIDTH : 0);
        int height = getItemHeight();
        int y = BORDER_WIDTH + ITEM_MARGIN;

        for (int i = first; i <= last ; i++) {
            paintItem(g, colors, getItem(i),
                      x, y, width, height,
                      isItemSelected(i),
                      isFocusedIndex(i));
            y += height + 2*ITEM_MARGIN;
        }

        if (vsbVis) {
            paintVSB(g, XComponentPeer.getSystemColors(), bounds);
        }
        if (hsbVis) {
            paintHSB(g, XComponentPeer.getSystemColors(), bounds);
        }
        peer.flush();
        // FIXME: if none of the items were focused, paint focus around the
        // entire list.  This is how java.awt.List should work.
    }

    /*
     * comment about what is painted (i.e. the focus rect
     */
    public void paintItem(Graphics g,
                          Color[] colors,
                          String string,
                          int x, int y, int width, int height,
                          boolean selected,
                          boolean focused) {
        //System.out.println("LP.pI(): x="+x+" y="+y+" w="+width+" h="+height);
        //g.setColor(colors[BACKGROUND_COLOR]);

        // FIXME: items shouldn't draw into the scrollbar

        if (selected) {
            g.setColor(colors[XComponentPeer.FOREGROUND_COLOR]);
        }
        else {
            g.setColor(colors[XComponentPeer.BACKGROUND_COLOR]);
        }
        g.fillRect(x, y, width, height);

        if (focused) {
            //g.setColor(colors[XComponentPeer.FOREGROUND_COLOR]);
            g.setColor(Color.BLACK);
            g.drawRect(x + FOCUS_INSET,
                       y + FOCUS_INSET,
                       width - 2*FOCUS_INSET,
                       height - 2*FOCUS_INSET);
        }

        if (selected) {
            g.setColor(colors[XComponentPeer.BACKGROUND_COLOR]);
        }
        else {
            g.setColor(colors[XComponentPeer.FOREGROUND_COLOR]);
        }
        g.setFont(font);
        //Rectangle clip = g.getClipBounds();
        //g.clipRect(x, y, width, height);
        //g.drawString(string, x + TEXT_SPACE, y + TEXT_SPACE + ITEM_MARGIN);

        int fontAscent = fm.getAscent();
        int fontDescent = fm.getDescent();

        g.drawString(string, x + TEXT_SPACE, y + (height + fm.getMaxAscent() - fm.getMaxDescent())/2);
        //g.clipRect(clip.x, clip.y, clip.width, clip.height);
    }

    boolean isItemSelected(int index) {
        Iterator itr = selected.iterator();
        while (itr.hasNext()) {
            Integer val = (Integer)itr.next();
            if (val.intValue() == index) {
                return true;
            }
        }
        return false;
    }

    public void paintVSB(Graphics g, Color colors[], Rectangle bounds) {
        int height = bounds.height - 2*BORDER_WIDTH - (hsbVis ? (SCROLLBAR_WIDTH-2) : 0);
        Graphics ng = g.create();

        g.setColor(colors[XComponentPeer.BACKGROUND_COLOR]);
        try {
            ng.translate(bounds.width - BORDER_WIDTH - SCROLLBAR_WIDTH,
                         BORDER_WIDTH);
            // Update scrollbar's size
            vsb.setSize(SCROLLBAR_WIDTH, bounds.height);
            vsb.paint(ng, colors, true);
        } finally {
            ng.dispose();
        }
    }

    public void paintHSB(Graphics g, Color colors[], Rectangle bounds) {

    }

    /*
     * Helper method for Components with integrated scrollbars.
     * Pass in the vertical and horizontal scroll bar (or null for none/hidden)
     * and the MouseWheelEvent, and the appropriate scrollbar will be scrolled
     * correctly.
     * Returns whether or not scrolling actually took place.  This will indicate
     * whether or not repainting is required.
     */
    static boolean doWheelScroll(XVerticalScrollbar vsb,
                                     XHorizontalScrollbar hsb,
                                     MouseWheelEvent e) {
        XScrollbar scroll = null;
        int wheelRotation;

        // Determine which, if any, sb to scroll
        if (vsb != null) {
            scroll = vsb;
        }
        else if (hsb != null) {
            scroll = hsb;
        }
        else { // Neither scrollbar is showing
            return false;
        }

        wheelRotation = e.getWheelRotation();

        // Check if scroll is necessary
        if ((wheelRotation < 0 && scroll.getValue() > scroll.getMinimum()) ||
            (wheelRotation > 0 && scroll.getValue() < scroll.getMaximum()) ||
            wheelRotation != 0) {

            int type = e.getScrollType();
            int incr;
            if (type == MouseWheelEvent.WHEEL_BLOCK_SCROLL) {
                incr = wheelRotation * scroll.getBlockIncrement();
            }
            else { // type is WHEEL_UNIT_SCROLL
                incr = e.getUnitsToScroll() * scroll.getUnitIncrement();
            }
            scroll.setValue(scroll.getValue() + incr);
            return true;
        }
        return false;
    }

    /*
     * Helper method for XChoicePeer with integrated vertical scrollbar.
     * Start or stop vertical scrolling when mouse dragged in / out the area of the list if it's required
     * Restoring Motif behavior
     * See 6243382 for more information
     */
    void trackMouseDraggedScroll(int mouseX, int mouseY, int listWidth, int listHeight){

        if (!mouseDraggedOutVertically){
            if (vsb.beforeThumb(mouseX, mouseY)) {
                vsb.setMode(AdjustmentEvent.UNIT_DECREMENT);
            } else {
                vsb.setMode(AdjustmentEvent.UNIT_INCREMENT);
            }
        }

        if(!mouseDraggedOutVertically && (mouseY < 0 || mouseY >= listHeight)){
            mouseDraggedOutVertically = true;
            vsb.startScrollingInstance();
        }

        if (mouseDraggedOutVertically && mouseY >= 0 && mouseY < listHeight && mouseX >= 0 && mouseX < listWidth){
            mouseDraggedOutVertically = false;
            vsb.stopScrollingInstance();
        }
    }

    /*
     * Helper method for XChoicePeer with integrated vertical scrollbar.
     * Stop vertical scrolling when mouse released in / out the area of the list if it's required
     * Restoring Motif behavior
     * see 6243382 for more information
     */
    void trackMouseReleasedScroll(){

        if (mouseDraggedOutVertically){
            mouseDraggedOutVertically = false;
            vsb.stopScrollingInstance();
        }

    }
}
