package com.aelitis.azureus.ui.swt.layout;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Layout;

public class SimpleReorderableListLayout extends Layout {
	
	public int margin;

	public boolean wrap;
	public boolean center;
	
	public int borderW = 3;
	public int borderH = 3;
	
	private int itemsPerRow;
	private int maxHeight = 0;
	private int maxWidth = 0;
	
	private int extraSpacing;
	
	private int previouswHint = SWT.DEFAULT;
	
	private boolean cached = false;
	private Point cachedSize = null;
	
	protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
		if(flushCache || ! cached || cachedSize == null) {
			
			Control[] controls = composite.getChildren();
			
			
			for(int i = 0 ; i < controls.length ; i++) {
				Object layoutData = controls[i].getLayoutData();
				if(layoutData != null && layoutData instanceof SimpleReorderableListLayoutData) {
					SimpleReorderableListLayoutData sData = (SimpleReorderableListLayoutData) layoutData;
					if(sData.height > maxHeight) maxHeight = sData.height;
					if(sData.width > maxWidth) maxWidth = sData.width;
				}
			}
			
			
			if((wHint != SWT.DEFAULT || previouswHint != SWT.DEFAULT) && wrap) {
				if(wHint != SWT.DEFAULT) {
					previouswHint  = wHint;
				} else {
					wHint = previouswHint;
				}
				itemsPerRow = 1;
				int width = 2 * borderW + maxWidth;
				while(width < wHint) {
					width += margin + maxWidth;
					if(width < wHint) {
						itemsPerRow++;
					}
				}
				if(center) {
					width = 2 * borderW + (margin + maxWidth) * itemsPerRow - margin;
					extraSpacing = itemsPerRow == 0 ? 0 : (wHint - width) / (itemsPerRow);
				} else {
					extraSpacing = 0;
				}
			} else {
				itemsPerRow = controls.length;
			}
			
			//Avoid dividing by 0 when there are no items
			int nbRows = itemsPerRow > 0 ? (controls.length+itemsPerRow-1) / itemsPerRow : 1;
			
			cached = true;
			cachedSize = new Point(2 * borderW + (maxWidth+margin) * itemsPerRow - margin, 2 * borderH + (margin + maxHeight) * nbRows - margin);
			
		} 
		
		return cachedSize;
		
	}

	protected void layout(Composite composite, boolean flushCache) {
		
		Control[] controls = composite.getChildren();
		List sortedControls = new ArrayList(controls.length);
		for(int i = 0 ; i < controls.length ; i++) {
			sortedControls.add(controls[i]);
		}
		
		Collections.sort(sortedControls,new Comparator() {
			public int compare(Object o1, Object o2) {
				Control c1 = (Control) o1;
				Control c2 = (Control) o2;
				Object layoutData1 = c1.getLayoutData();
				Object layoutData2 = c2.getLayoutData();
				if(layoutData1 == null || ! (layoutData1 instanceof SimpleReorderableListLayoutData) ) return 0;
				if(layoutData2 == null || ! (layoutData2 instanceof SimpleReorderableListLayoutData) ) return 0;
				SimpleReorderableListLayoutData data1 = (SimpleReorderableListLayoutData) layoutData1;
				SimpleReorderableListLayoutData data2 = (SimpleReorderableListLayoutData) layoutData2;
				return data1.position - data2.position;
			}
		});
		
		for(int i = 0 ; i < sortedControls.size() ; i++) {
			int xn = i % itemsPerRow;
			int yn = i / itemsPerRow;
			Control control = (Control) sortedControls.get(i);
			//int x = borderW + (margin + maxWidth + extraSpacing) * xn + extraSpacing;
			int x = borderW + (margin + maxWidth + extraSpacing) * xn;
			int y = borderH + (margin + maxHeight) * yn;
			control.setLocation(x,y);
			//control.setBounds(x,y,maxWidth,maxHeight);
			control.setBounds(x,y,maxWidth + extraSpacing,maxHeight);
		}
	
	}

}
