package cnp.ew.slider;

import java.awt.*;
import cnp.ew.util.*;
import cnp.ew.displayer.*;
import cnp.ew.image.*;
import cnp.ew.lightweight.*;
import cnp.ew.scrolling.*;

abstract public class CpAbstractSliderLc extends CpAbstractLc implements CpTimerUser
{

    int min, max, pageSize, value;
    int orientation;
    int dragOffset;
    boolean dragging = false;
    boolean paging = false;
    int savedValue;
    boolean paged;
    boolean usesFocus;

    CpTimedIntervalPolicy thumbPressIntervalPolicy = new CpSteppedTimedIntervalPolicy(6, -2, 400, 250);


    public CpAbstractSliderLc(int newOrientation)
    {
        orientation = newOrientation;
        min = 0;
        max = 100;
        pageSize = 10;
        value = 0;
        usesFocus = true;
    }

    public int getValue()
    {
        return value;
    }

    public void moveBy(int moveAmount)
    {
        value += moveAmount;
        boundsCheckValue();
        repaint();
    }

    void boundsCheckValue()
    {
        value = Math.max(min, value);
        value = Math.min(value, max - getWindowSize());
    }

    public void paint(Graphics g, Rectangle clip)
    {
        paintBackground(g);
        paintThumb(g);
    }

    Rectangle getThumbRect()
    {
        int startPix = getThumbStartPixel();
        Rectangle clientRect = getClientRect();
        if (orientation == CpScrollbarLc.VERTICAL) {
            return new Rectangle(clientRect.x, clientRect.y + startPix, clientRect.width, getThumbSizeInPixels());
        } else {
            return new Rectangle(clientRect.x + startPix, clientRect.y, getThumbSizeInPixels(), clientRect.height);
        }
    }

    int getScaleDimension()
    {
        return getDimension();
    }

    int getDimension()
    {
        if (orientation == CpScrollbarLc.VERTICAL) {
            return getClientRect().height;
        } else {
            return getClientRect().width;
        }
    }

    int getCoord(int x, int y)
    {
        if (orientation == CpScrollbarLc.VERTICAL) {
            return y;
        } else {
            return x;
        }
    }

    int getThumbStartPixel()
    {
        return value * getScaleDimension() / (max - min);
    }

    public boolean mouseDown(Event e, int x, int y)
    {
        savedValue = value;
        if (getCoord(x, y) < getThumbStartPixel() || getCoord(x, y) > getThumbStartPixel() + getThumbSizeInPixels()) {
            paging = true;
            paged = false;
            startTimer();
        } else {
            dragOffset = getCoord(x, y) - getThumbStartPixel();
            dragging = true;
            notifyObservers(CpEvent.START_DRAG_SCROLL);
        }
        return true;
    }

    void mouseDrag(int x, int y)
    {
        int oldValue = value;
        if (paging) {
            if (getCoord(x, y) < getThumbStartPixel()) {
                value = value - getAmountToPage();
                boundsCheckValue();
                paged = true;
                notifyObservers(SLIDER_PAGED, new Integer(value));
                repaint();
            } else if (getCoord(x, y) > getThumbStartPixel() + getThumbSizeInPixels()) {
                value = value + getAmountToPage();
                boundsCheckValue();
                paged = true;
                notifyObservers(SLIDER_PAGED, new Integer(value));
                repaint();
            }

        } else if (dragging) {
            value = (getCoord(x, y) - dragOffset) * (max - min) / getScaleDimension();
            boundsCheckValue();
            if (oldValue != value) {
                repaint();
                notifyObservers(SLIDER_DRAGGING, new Integer(value));
            }
        }
        if (oldValue != value) {
            notifyObservers(OBJECT_CHANGING, new Integer(value));
        }
    }

    public boolean mouseDrag(Event e, int x, int y)
    {
        mouseDrag(x, y);
        return true;
    }

    public boolean mouseUp(Event e, int x, int y)
    {
        // Can't guarantee I get a mouseDrag (in Netscape I don't)
        if (paging && !paged) {
            mouseDrag(x, y);
        }
        if (dragging) {
            notifyObservers(END_DRAG_SCROLL);
        }
        dragging = false;
        paging = false;
        stopTimer();
        if (savedValue != value) {
            notifyObservers(OBJECT_CHANGED, new Integer(value));
        }
        return true;
    }


    void startTimer()
    {
        thumbPressIntervalPolicy.initialize();
        CpTimer.getDefaultTimer().register(this, thumbPressIntervalPolicy.getNextInterval());
    }

    void stopTimer()
    {
        CpTimer.getDefaultTimer().unregister(this);
    }

    public long timerEvent(int timerType) {
        Point mouseLocation = mouseLocation();
        mouseDrag(mouseLocation.x, mouseLocation.y);
        return thumbPressIntervalPolicy.getNextInterval();
    }

    public boolean usesFocus()
    {
        return usesFocus;
    }

    public void setUsesFocus(boolean usesFocus)
    {
        this.usesFocus = usesFocus;
    }

    abstract int getWindowSize();
    abstract int getThumbSizeInPixels();
    abstract void paintBackground(Graphics g);
    abstract void paintThumb(Graphics g);
    abstract int getAmountToPage();
}

