/*******************************************************************************
 * Copyright (c) 2000, 2008 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.widgets;

import intrinsic.flash.display.DisplayObject;
import intrinsic.mx.controls.HScrollBar;
import intrinsic.mx.controls.VScrollBar;
import intrinsic.mx.core.ScrollControlBase;
import intrinsic.mx.events.ScrollEvent;
import intrinsic.mx.events.ScrollEventDetail;

import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.events.*;

public class ScrollBar extends Widget {
	Scrollable parent;
	int minimum, maximum, selection, thumb, increment, pageIncrement;
	
ScrollBar (Scrollable parent, int style) {
	super (parent, checkStyle (style));
	this.parent = parent;
	createWidget ();
}

public void addSelectionListener (SelectionListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener(listener);
	addListener (SWT.Selection,typedListener);
	addListener (SWT.DefaultSelection,typedListener);
}

static int checkStyle (int style) {
	return checkBits (style, SWT.HORIZONTAL, SWT.VERTICAL, 0, 0, 0, 0);
}

intrinsic.mx.controls.scrollClasses.ScrollBar getBar() {
	ScrollControlBase widget = (ScrollControlBase)parent.object;
	if ((style & SWT.H_SCROLL) != 0) {
		for (int i = 0; i < widget.numChildren; i++) {
			DisplayObject child = widget.getChildAt(i);
			if (child instanceof HScrollBar) {
				return (HScrollBar)child;
			}
		}
	} else {
		for (int i = 0; i < widget.numChildren; i++) {
			DisplayObject child = widget.getChildAt(i);
			if (child instanceof VScrollBar) {
				return (VScrollBar)child;
			}
		}
	}
	return null;
}

public boolean getEnabled () {
	checkWidget ();
	return (state & DISABLED) == 0;
}

public int getIncrement () {
	checkWidget ();
	intrinsic.mx.controls.scrollClasses.ScrollBar bar = getBar();
	if (bar != null) return (int)bar.lineScrollSize;
	return increment;
}

public int getMaximum () {
	checkWidget ();
	intrinsic.mx.controls.scrollClasses.ScrollBar bar = getBar();
	if (bar != null) return (int)(bar.maxScrollPosition + bar.pageSize);
	return maximum + thumb;
}

public int getMinimum () {
	checkWidget ();
	intrinsic.mx.controls.scrollClasses.ScrollBar bar = getBar();
	if (bar != null) return (int)bar.minScrollPosition;
	return minimum;
}

public int getPageIncrement () {
	checkWidget ();
	intrinsic.mx.controls.scrollClasses.ScrollBar bar = getBar();
	if (bar != null) return (int)bar.pageScrollSize;
	return pageIncrement;
}

public Scrollable getParent () {
	checkWidget();
	return parent;
}

public int getSelection () {
	checkWidget ();
	intrinsic.mx.controls.scrollClasses.ScrollBar bar = getBar();
	if (bar != null) return (int)bar.scrollPosition;
	return selection;
}

public Point getSize () {
	checkWidget ();
	intrinsic.mx.controls.scrollClasses.ScrollBar bar = getBar();
	if (bar != null) return new Point(Math.max(0, (int)bar.width), Math.max(0, (int)bar.height));
	int thickness = (int)intrinsic.mx.controls.scrollClasses.ScrollBar.THICKNESS;
	return new Point(thickness, thickness);
}

public int getThumb () {
	checkWidget ();
	intrinsic.mx.controls.scrollClasses.ScrollBar bar = getBar();
	if (bar != null) return (int)bar.pageSize;
	return thumb;
}

public boolean getVisible () {
	checkWidget ();
	return (state & HIDDEN) == 0;
}

public boolean isEnabled () {
	checkWidget();
	return getEnabled () && parent.isEnabled ();
}

public boolean isVisible () {
	checkWidget();
	return getVisible () && parent.isVisible ();
}

void releaseHandle () {
	super.releaseHandle ();
	object = null;
	parent = null;
}

void releaseParent () {
	super.releaseParent ();
	if (parent.horizontalBar == this) parent.horizontalBar = null;
	if (parent.verticalBar == this) parent.verticalBar = null;
}

public void removeSelectionListener (SelectionListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook (SWT.Selection, listener);
	eventTable.unhook (SWT.DefaultSelection,listener);	
}

void scrollHandler(ScrollEvent event) {
	int detail = 0;
	if (event.detail == ScrollEventDetail.LINE_UP) {
		detail = SWT.ARROW_UP;
	} else if (event.detail == ScrollEventDetail.LINE_DOWN) {
		detail = SWT.ARROW_DOWN;
	} else if (event.detail == ScrollEventDetail.LINE_LEFT) {
		detail = SWT.ARROW_DOWN;
	} else if (event.detail == ScrollEventDetail.LINE_RIGHT) {
		detail = SWT.ARROW_UP;
	} else if (event.detail == ScrollEventDetail.PAGE_UP) {
		detail = SWT.PAGE_UP;
	} else if (event.detail == ScrollEventDetail.PAGE_DOWN) {
		detail = SWT.PAGE_DOWN;
	} else if (event.detail == ScrollEventDetail.PAGE_LEFT) {
		detail = SWT.PAGE_DOWN;
	} else if (event.detail == ScrollEventDetail.PAGE_RIGHT) {
		detail = SWT.PAGE_UP;
	} else if (event.detail == ScrollEventDetail.THUMB_TRACK) {
		detail = SWT.DRAG;
	} else if (event.detail == ScrollEventDetail.THUMB_POSITION) {
		detail = SWT.NONE;
	} else if (event.detail == ScrollEventDetail.AT_TOP) {
		detail = SWT.HOME;
	} else if (event.detail == ScrollEventDetail.AT_BOTTOM) {
		detail = SWT.END;
	} else if (event.detail == ScrollEventDetail.AT_LEFT) {
		detail = SWT.HOME;
	} else if (event.detail == ScrollEventDetail.AT_RIGHT) {
		detail = SWT.END;
	}
	sendSelection(detail, (int)event.position);
}

void sendSelection (int detail, int selection) {
	this.selection = selection;
	Event event = new Event ();
	event.detail = detail;
	sendEvent (SWT.Selection, event);
}

public void setEnabled (boolean enabled) {
	checkWidget();
	if (((state & DISABLED) == 0) == enabled) return;
	state = enabled ? state & ~DISABLED : state | DISABLED;
	object.enabled = enabled;
}

public void setIncrement (int value) {
	checkWidget ();
	if (value < 1) return;
	increment = value;
	intrinsic.mx.controls.scrollClasses.ScrollBar bar = getBar();
	if (bar != null) {
		bar.lineScrollSize = value;
	}
}

public void setMaximum (int value) {
	checkWidget ();
	if (value < 0) return;
	if (value <= minimum) return;
	if (value - minimum < thumb) {
		thumb = value - minimum;
	}
	maximum = value - thumb;
	intrinsic.mx.controls.scrollClasses.ScrollBar bar = getBar();
	if (bar != null) {
		bar.setScrollProperties (thumb, minimum, maximum, pageIncrement);
	}
}

public void setMinimum (int value) {
	checkWidget ();
	if (value < 0) return;
	if (value >= maximum + thumb) return;
	if (maximum + thumb - value < thumb) {
		thumb = maximum + thumb - value;
	}
	minimum = value;
	intrinsic.mx.controls.scrollClasses.ScrollBar bar = getBar();
	if (bar != null) {
		bar.setScrollProperties (thumb, minimum, maximum, pageIncrement);
	}
}

public void setPageIncrement (int value) {
	checkWidget ();
	if (value < 1) return;
	pageIncrement = value;
	intrinsic.mx.controls.scrollClasses.ScrollBar bar = getBar();
	if (bar != null) {
		bar.setScrollProperties (thumb, minimum, maximum, pageIncrement);
	}
}

public void setSelection (int value) {
	checkWidget ();
	if (value < minimum || value > maximum) return;
	selection = value;
	intrinsic.mx.controls.scrollClasses.ScrollBar bar = getBar();
	if (bar != null) {
		bar.scrollPosition = value;
	}
	//TODO does not set verticalScrollPosition in ScrollControlBase
}

public void setThumb (int value) {
	checkWidget ();
	if (value < 1) return;
	value = Math.min (value, maximum + thumb - minimum);
	maximum = maximum + thumb - value;
	thumb = value;
	intrinsic.mx.controls.scrollClasses.ScrollBar bar = getBar();
	if (bar != null) {
		bar.setScrollProperties (thumb, minimum, maximum, pageIncrement);
	}
}

public void setValues (int selection, int minimum, int maximum, int thumb, int increment, int pageIncrement) {
	checkWidget();
	if (minimum < 0) return;
	if (maximum < 0) return;
	if (thumb < 1) return;
	if (increment < 1) return;
	if (pageIncrement < 1) return;
	thumb = Math.min (thumb, maximum - minimum);
	this.minimum = minimum;
	this.maximum = maximum - thumb;
	this.thumb = thumb;
	this.selection = selection;
	this.increment = increment;
	this.pageIncrement = pageIncrement;
	intrinsic.mx.controls.scrollClasses.ScrollBar bar = getBar();
	if (bar != null) {
		bar.setScrollProperties (this.thumb, this.minimum, this.maximum, this.pageIncrement);
		bar.lineScrollSize = increment;
		bar.scrollPosition = selection;
	}
}

public void setVisible (boolean visible) {
	checkWidget ();
	if (((state & HIDDEN) == 0) == visible) return;
	if (visible) {
		sendEvent (SWT.Show);
		if (isDisposed ()) return;
	}
	state = visible ? state & ~HIDDEN : state | HIDDEN;
	intrinsic.mx.controls.scrollClasses.ScrollBar bar = getBar ();
	if (bar != null) bar.visible = visible;
	parent.object.invalidateDisplayList();
	if (!visible) {
		sendEvent (SWT.Hide);
		if (isDisposed ()) return;
	}
}
}
