/*
 * Copyright 2006 Mask@ Project.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.maskat.ide.editors;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Sash;
import org.maskat.ide.MaskatIDEUtil;

public class MaskatEditor2 extends MaskatEditor {

	Sash hSash;

	static final int SASH_WIDTH = 4;

	static final int SASH_LIMIT = 5;

	// 下のhidden領域の比率を記憶する
	private float currentDownPartRatio = 1f / 12f;

	private HiddenEditComposite hiddenEditComp;

	/**
	 * このエディターのwidget
	 */
	Composite composite;

	/**
	 * 親クラスのwidget。<br>
	 * このエディターは<em>親のwidgetを子widgetとして</em>、<br>
	 * sashとhiddenEditCompを加えて作られるので、
	 */
	Composite childComposite;

	public void createPartControl(final Composite parent) {

		composite = new Composite(parent, SWT.NONE);
		composite.setLayout(new FillLayout());
		hiddenEditComp = new HiddenEditComposite(composite, SWT.NONE);
		MenuManager mm = new MenuManager();
		hiddenEditComp.setMenu(mm.createContextMenu(hiddenEditComp));
		mm.add(new Action("変数を追加") {
			public void run() {
				InputDialog dialog = new InputDialog(parent.getShell(), "Mask@ IDE",
						"変数を追加", null, VarNameInputValidator.validator);
				int ret = dialog.open();
				if (ret == Window.OK && !"".equals(dialog.getValue().trim())) {
					hiddenEditComp.addEle(dialog.getValue());
				}
			}
		});

		hSash = new Sash(composite, SWT.HORIZONTAL | SWT.SMOOTH);

		hSash.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				Rectangle rect = hSash.getParent().getClientArea();
				event.y = Math.min(Math.max(event.y, SASH_LIMIT), rect.height
						- SASH_LIMIT);
				if (event.detail != SWT.DRAG) {
					hSash.setBounds(event.x, event.y, event.width, event.height);
					// 新たな比率を計算
					int clientHeightWithoutSash = rect.height - SASH_WIDTH;
					currentDownPartRatio = ((float) (clientHeightWithoutSash - event.y))
							/ (float) clientHeightWithoutSash;
					layout();
				}
			}

		});

		hSash.addControlListener(new ControlAdapter() {
			public void controlResized(ControlEvent event) {
				resized();
			}
		});
		super.createPartControl(composite);
		childComposite = super.getControl();
	}

	protected Composite getControl() {
		return composite;
	}

	protected void initializeGraphicalViewer() {
		super.initializeGraphicalViewer();

		//XXX layout objの処理はレイアウト切り替わるたびに行わなければいけません。
		Set layoutDefObjNames = new HashSet();
		getCurrentLayoutDef().getAllChildComponentNames(layoutDefObjNames);

		Set eventDefObjNames = layout.getAllObjNames();
		eventDefObjNames.removeAll(layoutDefObjNames);

		for (Iterator it = eventDefObjNames.iterator(); it != null && it.hasNext();) {
			String name = (String) it.next();
			hiddenEditComp.addEle(name);
		}
		String objsStr = getCurrentLayoutDef().getObjs();
		if (objsStr != null && !"".equals(objsStr.trim())) {
			String[] objs = objsStr.split(",");
			if (objs != null) {
				for (int i = 0; i < objs.length; i++) {
					hiddenEditComp.addEle(objs[i]);
				}
			}
		}
	};

	private void layout() {

		Rectangle clientArea = composite.getClientArea();
		Rectangle hSashBounds = hSash.getBounds();

		childComposite.setBounds(0, 0, clientArea.width, hSashBounds.y);
		hiddenEditComp.setBounds(0, hSashBounds.y + SASH_WIDTH, clientArea.width,
				clientArea.height - hSashBounds.y - SASH_WIDTH);
	}

	/**
	 * Handle the shell resized event.
	 */
	void resized() {

		/* Get the client area for the shell */
		Rectangle clientArea = composite.getClientArea();

		int upPartHeight = new Float((clientArea.height - SASH_WIDTH)
				* (1 - currentDownPartRatio)).intValue();
		Rectangle upBounds = new Rectangle(0, 0, clientArea.width, upPartHeight);
		childComposite.setBounds(upBounds);
		hiddenEditComp.setBounds(0, upPartHeight + SASH_WIDTH, clientArea.width,
				clientArea.height - upPartHeight - SASH_WIDTH);
		hSash.setBounds(0, upBounds.height, clientArea.width, SASH_WIDTH);
	}

	private class HiddenEditComposite extends Composite {
		public HiddenEditComposite(Composite parent, int style) {
			super(parent, style);
			RowLayout layout = new RowLayout();
			layout.pack = false;
			layout.justify = true;
			layout.wrap = true;
			this.setLayout(layout);
		}

		private List hiddenObjNames = new ArrayList();

		public void addEle(String name) {
			if (!hiddenObjNames.contains(name)) {
				final Button button = new Button(this, SWT.NONE);
				button.setText(name);
				hiddenObjNames.add(name);
				MenuManager mm = new MenuManager();
				button.setMenu(mm.createContextMenu(button));
				mm.add(new Action("変数を削除") {
					public void run() {
						boolean ret = MessageDialog.openQuestion(button.getShell(),
								"Mask@ IDE", "「" + button.getText()
										+ "」変数を削除します、よろしいですか？");
						if (ret) {
							Composite parent = button.getParent();
							hiddenObjNames.remove(button.getText());
							button.dispose();
							parent.layout();
						}
					}
				});
				mm.add(new Action("名前変更") {
					public void run() {
						InputDialog dialog = new InputDialog(button.getShell(),
								"Mask@ IDE", "変数名称変更", button.getText(),
								VarNameInputValidator.validator);
						int ret = dialog.open();
						if (ret == Window.OK && !"".equals(dialog.getValue().trim())) {
							hiddenObjNames.remove(button.getText());
							button.setText(dialog.getValue());
							hiddenObjNames.add(button.getText());
						}
					}
				});
				button.addSelectionListener(new SelectionListener() {
					public void widgetSelected(SelectionEvent e) {
						MaskatIDEUtil.getMaskatEditView().acceptData(button.getText());
					}

					public void widgetDefaultSelected(SelectionEvent e) {
					}
				});
				this.layout();
			}
		}

		public boolean delEle(String name) {
			for (Iterator it = hiddenObjNames.iterator(); it.hasNext();) {
				if (name.equals(it.next())) {
					it.remove();
					return true;
				}
			}
			return false;
		}

		// private class NameButtonPair {
		// private String name;
		//
		// private Button button;
		//
		// public NameButtonPair(String name, Button button) {
		// this.name = name;
		// this.button = button;
		// }
		//
		// public Button getButton() {
		// return button;
		// }
		//
		// public String getName() {
		// return name;
		// }
		//
		// }
	}
}
