package jp.co.cybec.laxide;

import java.io.File;

import jp.co.cybec.laxide.editParts.LetsAjaxBodyEditPart;
import jp.co.cybec.laxide.editParts.LetsAjaxEditPartFactory;
import jp.co.cybec.laxide.file.LetsAjaxLayoutFileManager;
import jp.co.cybec.laxide.model.base.LetsAjax2ColumnHeaderLayoutModel;
import jp.co.cybec.laxide.model.base.LetsAjax2ColumnLayoutModel;
import jp.co.cybec.laxide.model.base.LetsAjaxBodyModel;
import jp.co.cybec.laxide.model.base.LetsAjaxButtonModel;
import jp.co.cybec.laxide.model.base.LetsAjaxChartModel;
import jp.co.cybec.laxide.model.base.LetsAjaxCheckBoxModel;
import jp.co.cybec.laxide.model.base.LetsAjaxComboBoxModel;
import jp.co.cybec.laxide.model.base.LetsAjaxImageModel;
import jp.co.cybec.laxide.model.base.LetsAjaxLabelModel;
import jp.co.cybec.laxide.model.base.LetsAjaxLayoutConstant;
import jp.co.cybec.laxide.model.base.LetsAjaxLinkButtonModel;
import jp.co.cybec.laxide.model.base.LetsAjaxPlainLayoutModel;
import jp.co.cybec.laxide.model.base.LetsAjaxRadioButtonModel;
import jp.co.cybec.laxide.model.base.LetsAjaxTextAreaModel;
import jp.co.cybec.laxide.model.base.LetsAjaxTextFieldModel;
import jp.co.cybec.laxide.model.base.LetsAjaxTextModel;
import jp.co.cybec.laxide.model.extension.LetsAjaxDataTableModel;
import jp.co.cybec.laxide.model.extension.YuiBasicAnimateModel;
import jp.co.cybec.laxide.model.extension.YuiCalendarModel;
import jp.co.cybec.laxide.model.js.YuiColorAnimateJSModel;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.gef.DefaultEditDomain;
import org.eclipse.gef.GraphicalViewer;
import org.eclipse.gef.KeyHandler;
import org.eclipse.gef.KeyStroke;
import org.eclipse.gef.palette.CreationToolEntry;
import org.eclipse.gef.palette.MarqueeToolEntry;
import org.eclipse.gef.palette.PaletteDrawer;
import org.eclipse.gef.palette.PaletteGroup;
import org.eclipse.gef.palette.PaletteRoot;
import org.eclipse.gef.palette.SelectionToolEntry;
import org.eclipse.gef.palette.ToolEntry;
import org.eclipse.gef.requests.SimpleFactory;
import org.eclipse.gef.ui.actions.ActionRegistry;
import org.eclipse.gef.ui.actions.AlignmentAction;
import org.eclipse.gef.ui.actions.DirectEditAction;
import org.eclipse.gef.ui.actions.GEFActionConstants;
import org.eclipse.gef.ui.parts.GraphicalEditorWithPalette;
import org.eclipse.gef.ui.parts.GraphicalViewerKeyHandler;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.SWT;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.actions.ActionFactory;

public class LetsAjaxEditor extends GraphicalEditorWithPalette {
	/*
	 * ビューです。
	 */
	private GraphicalViewer laxView;

	/**
	 * コンストラクタ
	 * 
	 */
	public LetsAjaxEditor() {
		setEditDomain(new DefaultEditDomain(this));
	}

	public void selectionChanged(IWorkbenchPart part, ISelection selection) {
		// getActivePage()がnullの場合は無視する
		if (part.getSite().getWorkbenchWindow().getActivePage() == null)
			return;
		super.selectionChanged(part, selection);
	}

	/**
	 * パレットに部品を表示している
	 * 
	 * @see org.eclipse.gef.ui.parts.GraphicalEditorWithPalette#getPaletteRoot()
	 */
	protected PaletteRoot getPaletteRoot() {
		// パレットのルート
		PaletteRoot root = new PaletteRoot();

		// モデル作成以外のツールを格納するグループ
		PaletteGroup toolGroup = new PaletteGroup("ツール");

		// '選択' ツールの作成と追加
		ToolEntry tool = new SelectionToolEntry();
		toolGroup.add(tool);
		root.setDefaultEntry(tool); // デフォルトでアクティブになるツール

		// '囲み枠' ツールの作成と追加
		tool = new MarqueeToolEntry();
		toolGroup.add(tool);

		// 作成したグループをルートに追加
		root.add(toolGroup);
		root.add(this.getBaseComponentGroup());
		root.add(this.getOtherComponentGroup());
		root.add(this.getServiceComponentGroup());
		root.add(this.getJSComponentGroup());
		root.add(this.getLauoutTemplateGroup());
		return root;
	}

	/**
	 * パレットへの基本部品配置
	 * 
	 * @return
	 */
	private PaletteDrawer getBaseComponentGroup() {
		// モデルの作成を行うツールを格納するグループ
		PaletteDrawer drawer = new PaletteDrawer("基本部品");

		// 文字列作成と追加
		ImageDescriptor textDescriptor = ImageDescriptor.createFromFile(
				LetsAjaxEditor.class, "text.gif");
		CreationToolEntry creationTextEntry = new CreationToolEntry("テキスト", // パレットに表示される文字列
				"TEXT", // ツールチップ
				new SimpleFactory(LetsAjaxTextModel.class), // モデルを作成するファクトリ
				textDescriptor, // パレットに表示する16X16のイメージ
				textDescriptor);// パレットに表示する24X24のイメージ
		drawer.add(creationTextEntry);

		// LABEL作成と追加
		ImageDescriptor descriptor = ImageDescriptor.createFromFile(
				LetsAjaxEditor.class, "label.gif");
		CreationToolEntry creationEntry = new CreationToolEntry("ラベル", // パレットに表示される文字列
				"LABEL", // ツールチップ
				new SimpleFactory(LetsAjaxLabelModel.class), // モデルを作成するファクトリ
				descriptor, // パレットに表示する16X16のイメージ
				descriptor);// パレットに表示する24X24のイメージ
		drawer.add(creationEntry);

		// BUTTONツールの作成と追加
		ImageDescriptor descriptor2 = ImageDescriptor.createFromFile(
				LetsAjaxEditor.class, "button.gif");
		CreationToolEntry creationEntry2 = new CreationToolEntry("ボタン", // パレットに表示される文字列
				"BUTTON", // ツールチップ
				new SimpleFactory(LetsAjaxButtonModel.class), // モデルを作成するファクトリ
				descriptor2, // パレットに表示する16X16のイメージ
				descriptor2);// パレットに表示する24X24のイメージ
		drawer.add(creationEntry2);

		// LinkButton
		ImageDescriptor linkButtonDescriptor = ImageDescriptor.createFromFile(
				LetsAjaxEditor.class, "linkbutton.gif");
		CreationToolEntry linkCreationEntry = new CreationToolEntry("リンク", // パレットに表示される文字列
				"Link", // ツールチップ
				new SimpleFactory(LetsAjaxLinkButtonModel.class), // モデルを作成するファクトリ
				linkButtonDescriptor, // パレットに表示する16X16のイメージ
				linkButtonDescriptor);// パレットに表示する24X24のイメージ
		drawer.add(linkCreationEntry);

		// RadioButton
		ImageDescriptor radioButtonDescriptor = ImageDescriptor.createFromFile(
				LetsAjaxEditor.class, "radiobutton.gif");
		CreationToolEntry radioCreationEntry = new CreationToolEntry("ラジオボタン", // パレットに表示される文字列
				"RadioButton", // ツールチップ
				new SimpleFactory(LetsAjaxRadioButtonModel.class), // モデルを作成するファクトリ
				radioButtonDescriptor, // パレットに表示する16X16のイメージ
				radioButtonDescriptor);// パレットに表示する24X24のイメージ
		drawer.add(radioCreationEntry);

		// CheckBox
		ImageDescriptor checkBoxDescriptor = ImageDescriptor.createFromFile(
				LetsAjaxEditor.class, "checkbox.gif");
		CreationToolEntry checkBoxCreationEntry = new CreationToolEntry(
				"チェックボックス", // パレットに表示される文字列
				"CheckBox", // ツールチップ
				new SimpleFactory(LetsAjaxCheckBoxModel.class), // モデルを作成するファクトリ
				checkBoxDescriptor, // パレットに表示する16X16のイメージ
				checkBoxDescriptor);// パレットに表示する24X24のイメージ
		drawer.add(checkBoxCreationEntry);

		// Text
		ImageDescriptor descriptor3 = ImageDescriptor.createFromFile(
				LetsAjaxEditor.class, "textfield.gif");
		CreationToolEntry creationEntry3 = new CreationToolEntry("テキストフィールド", // パレットに表示される文字列
				"TextField", // ツールチップ
				new SimpleFactory(LetsAjaxTextFieldModel.class), // モデルを作成するファクトリ
				descriptor3, // パレットに表示する16X16のイメージ
				descriptor3);// パレットに表示する24X24のイメージ
		drawer.add(creationEntry3);

		// TextArea
		ImageDescriptor textAreaDescriptor = ImageDescriptor.createFromFile(
				LetsAjaxEditor.class, "textarea.gif");
		CreationToolEntry textAreaCreationEntry = new CreationToolEntry(
				"テキストエリア", // パレットに表示される文字列
				"TextArea", // ツールチップ
				new SimpleFactory(LetsAjaxTextAreaModel.class), // モデルを作成するファクトリ
				textAreaDescriptor, // パレットに表示する16X16のイメージ
				textAreaDescriptor);// パレットに表示する24X24のイメージ
		drawer.add(textAreaCreationEntry);

		// SELECT BOX
		ImageDescriptor selectBoxDescriptor = ImageDescriptor.createFromFile(
				LetsAjaxEditor.class, "combo.gif");
		CreationToolEntry selectBoxCreationEntry = new CreationToolEntry(
				"コンボボックス", // パレットに表示される文字列
				"ComboBox", // ツールチップ
				new SimpleFactory(LetsAjaxComboBoxModel.class), // モデルを作成するファクトリ
				selectBoxDescriptor, // パレットに表示する16X16のイメージ
				selectBoxDescriptor);// パレットに表示する24X24のイメージ
		drawer.add(selectBoxCreationEntry);

		// IMAGE
		ImageDescriptor imageDescriptor = ImageDescriptor.createFromFile(
				LetsAjaxEditor.class, "image.gif");
		CreationToolEntry imageCreationEntry = new CreationToolEntry("イメージ", // パレットに表示される文字列
				"Image", // ツールチップ
				new SimpleFactory(LetsAjaxImageModel.class), // モデルを作成するファクトリ
				imageDescriptor, // パレットに表示する16X16のイメージ
				imageDescriptor);// パレットに表示する24X24のイメージ
		drawer.add(imageCreationEntry);

		return drawer;
	}

	/**
	 * パレットへの拡張部品の表示
	 * 
	 * @return
	 */
	private PaletteDrawer getOtherComponentGroup() {

		// 他部品用グループ
		PaletteDrawer otherDrawer = new PaletteDrawer("拡張部品");

		// YUIカレンダ用JS
		ImageDescriptor yuiCalendarDescriptor = ImageDescriptor.createFromFile(
				LetsAjaxEditor.class, "jsControl1.gif");
		CreationToolEntry yuiCalendarCreationEntry = new CreationToolEntry(
				"YUIカレンダ", // パレットに表示される文字列
				"YUIカレンダ", // ツールチップ
				new SimpleFactory(YuiCalendarModel.class), // モデルを作成するファクトリ
				yuiCalendarDescriptor, // パレットに表示する16X16のイメージ
				yuiCalendarDescriptor);// パレットに表示する24X24のイメージ
		otherDrawer.add(yuiCalendarCreationEntry);

		// YUIアニメーション用JS
		ImageDescriptor yuiAnimateDescriptor = ImageDescriptor.createFromFile(
				LetsAjaxEditor.class, "jsControl1.gif");
		CreationToolEntry yuiAnimateCreationEntry = new CreationToolEntry(
				"YUIアニメーション", // パレットに表示される文字列
				"YUIアニメーション", // ツールチップ
				new SimpleFactory(YuiBasicAnimateModel.class), // モデルを作成するファクトリ
				yuiAnimateDescriptor, // パレットに表示する16X16のイメージ
				yuiAnimateDescriptor);// パレットに表示する24X24のイメージ
		otherDrawer.add(yuiAnimateCreationEntry);
		return otherDrawer;
	}

	/**
	 * 汎用サービスのパレットへの配置
	 * 
	 * @return
	 */
	private PaletteDrawer getServiceComponentGroup() {
		// 汎用サービス用部品グループ
		PaletteDrawer serviceDrawer = new PaletteDrawer("汎用サービス部品");
		ImageDescriptor serviceDescriptor = ImageDescriptor.createFromFile(
				LetsAjaxEditor.class, "dataTable.gif");
		CreationToolEntry serviceCreationEntry = new CreationToolEntry(
				"データテーブル", // パレットに表示される文字列
				"Tablet", // ツールチップ
				new SimpleFactory(LetsAjaxDataTableModel.class), // モデルを作成するファクトリ
				serviceDescriptor, // パレットに表示する16X16のイメージ
				serviceDescriptor);// パレットに表示する24X24のイメージ
		serviceDrawer.add(serviceCreationEntry);

		// chart用JS
		ImageDescriptor ChartJsDescriptor = ImageDescriptor.createFromFile(
				LetsAjaxEditor.class, "jsControl1.gif");
		CreationToolEntry chartJsCreationEntry = new CreationToolEntry("チャート", // パレットに表示される文字列
				"チャート", // ツールチップ
				new SimpleFactory(LetsAjaxChartModel.class), // モデルを作成するファクトリ
				ChartJsDescriptor, // パレットに表示する16X16のイメージ
				ChartJsDescriptor);// パレットに表示する24X24のイメージ
		serviceDrawer.add(chartJsCreationEntry);
		return serviceDrawer;
	}

	/**
	 * JavaScript部品のパレットへの配置
	 * 
	 * @return
	 */
	private PaletteDrawer getJSComponentGroup() {
		// JS用グループ
		PaletteDrawer jsDrawer = new PaletteDrawer("JS部品");

		// YUIアニメーション(カラー)用JS
		ImageDescriptor yuiColorAnimateJsDescriptor = ImageDescriptor
				.createFromFile(LetsAjaxEditor.class, "jsControl1.gif");
		CreationToolEntry yuiColorAnimateJsCreationEntry = new CreationToolEntry(
				"YUIアニメーション(カラー)用JS", // パレットに表示される文字列
				"YUIアニメーション(カラー)用JS", // ツールチップ
				new SimpleFactory(YuiColorAnimateJSModel.class), // モデルを作成するファクトリ
				yuiColorAnimateJsDescriptor, // パレットに表示する16X16のイメージ
				yuiColorAnimateJsDescriptor);// パレットに表示する24X24のイメージ
		jsDrawer.add(yuiColorAnimateJsCreationEntry);

		return jsDrawer;
	}

	/**
	 * レイアウトテンプレートのグループパレットへの配置
	 * 
	 * @return
	 */
	private PaletteDrawer getLauoutTemplateGroup() {
		// 
		PaletteDrawer jsDrawer = new PaletteDrawer("レイアウト");
		ImageDescriptor layoutDescriptor = ImageDescriptor.createFromFile(
				LetsAjaxEditor.class, "jsControl1.gif");
		CreationToolEntry layoutCreationEntry = new CreationToolEntry("プレーン", // パレットに表示される文字列
				"プレーン", // ツールチップ
				new SimpleFactory(LetsAjaxPlainLayoutModel.class), // モデルを作成するファクトリ
				layoutDescriptor, // パレットに表示する16X16のイメージ
				layoutDescriptor);// パレットに表示する24X24のイメージ
		jsDrawer.add(layoutCreationEntry);

		ImageDescriptor layoutDescriptor2 = ImageDescriptor.createFromFile(
				LetsAjaxEditor.class, "jsControl1.gif");
		CreationToolEntry layout2CreationEntry = new CreationToolEntry("２段組", // パレットに表示される文字列
				"２段組", // ツールチップ
				new SimpleFactory(LetsAjax2ColumnLayoutModel.class), // モデルを作成するファクトリ
				layoutDescriptor2, // パレットに表示する16X16のイメージ
				layoutDescriptor2);// パレットに表示する24X24のイメージ
		jsDrawer.add(layout2CreationEntry);

		ImageDescriptor layoutDescriptor3 = ImageDescriptor.createFromFile(
				LetsAjaxEditor.class, "jsControl1.gif");
		CreationToolEntry layout3CreationEntry = new CreationToolEntry(
				"ヘッダー付２段組", // パレットに表示される文字列
				"ヘッダー付２段組", // ツールチップ
				new SimpleFactory(LetsAjax2ColumnHeaderLayoutModel.class), // モデルを作成するファクトリ
				layoutDescriptor3, // パレットに表示する16X16のイメージ
				layoutDescriptor3);// パレットに表示する24X24のイメージ
		jsDrawer.add(layout3CreationEntry);

		return jsDrawer;
	}

	/**
	 * LAXファイル名をエディタから取得する
	 * 
	 * @return
	 */
	private String getLaxFileName() {
		IFileEditorInput input = (IFileEditorInput) getEditorInput();
		if (input != null && input.getFile().getLocation() != null) {
			String fileName = input.getFile().getLocation().toString();
			return fileName;
		}
		return null;

	}

	/**
	 * ファイルの保存。
	 * 
	 * @see org.eclipse.ui.part.EditorPart#doSave(org.eclipse.core.runtime.IProgressMonitor)
	 */
	public void doSave(IProgressMonitor monitor) {
		// Save処理
		String file = this.getLaxFileName();

		LetsAjaxBodyEditPart part = (LetsAjaxBodyEditPart) this.laxView
				.getContents();
		LetsAjaxLayoutFileManager manager = new LetsAjaxLayoutFileManager();
		manager.createLayoutFile((LetsAjaxBodyModel) part.getModel(), file);
		getCommandStack().markSaveLocation();
	}

	/**
	 * ファイルの保存
	 * 
	 * @see org.eclipse.gef.ui.parts.GraphicalEditor#doSaveAs()
	 */
	public void doSaveAs() {
		// Save処理
		super.doSaveAs();
	}

	/**
	 * ファイルに変更があったかチェックするフラグ
	 * 
	 * @see org.eclipse.gef.ui.parts.GraphicalEditor#isDirty()
	 */
	public boolean isDirty() {
		return getCommandStack().isDirty();
	}

	// オーバーライド
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.gef.ui.parts.GraphicalEditor#commandStackChanged(java.util.EventObject)
	 */
	public void commandStackChanged(java.util.EventObject event) {
		// 保存アクションの有効/無効を切り替える
		firePropertyChange(IEditorPart.PROP_DIRTY);
		super.commandStackChanged(event);
	}

	// オーバーライド
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.gef.ui.parts.GraphicalEditor#isSaveAsAllowed()
	 */
	public boolean isSaveAsAllowed() {
		// TODO 自動生成されたメソッド・スタブ
		return false;
	}

	/**
	 * IDEの初期表示処理
	 * 
	 * @see org.eclipse.gef.ui.parts.GraphicalEditor#initializeGraphicalViewer()
	 */
	protected void initializeGraphicalViewer() {
		GraphicalViewer viewer = getGraphicalViewer();
		this.setLaxView(viewer);

		// 最上位のモデルの設定
		LetsAjaxBodyModel parent = new LetsAjaxBodyModel();// 親つくる
		parent.setType(LetsAjaxLayoutConstant.LETSAJAX_BODY);

		// 初期表示の読み込み
		String file = this.getLaxFileName();
		if (file == null || (file != null && "".equals(file))) {
			// デフォルトのワークスペースにLAXファイルがあった場合の
			// 読み込み処理
			String filePath = Platform.getInstanceLocation().getURL().getPath();
			file = filePath + this.getTitleToolTip();
		}
		File laxFile = new File(file);
		if (laxFile.exists()) {
			LetsAjaxLayoutFileManager fileManager = new LetsAjaxLayoutFileManager();
			fileManager.loadLayoutFile(laxFile.getAbsolutePath(), parent);
		}

		viewer.setContents(parent);// 親を最上位に
		IFile iFile = ((IFileEditorInput) this.getEditorInput()).getFile();
		String mame = iFile.getName();
		this.setTitle(mame);

	}

	/**
	 * キーボードとアクションを関連付ける
	 * 
	 * @see org.eclipse.gef.ui.parts.GraphicalEditor#configureGraphicalViewer()
	 */
	protected void configureGraphicalViewer() {
		super.configureGraphicalViewer();

		GraphicalViewer viewer = getGraphicalViewer();
		// EditPartFactoryの作成と設定
		viewer.setEditPartFactory(new LetsAjaxEditPartFactory());

		LetsAjaxContextMenuProvider contextProvider = new LetsAjaxContextMenuProvider(
				viewer);
		contextProvider.setRegistry(getActionRegistry());
		viewer.setContextMenu(contextProvider);
		getSite().registerContextMenu(contextProvider, viewer);

		// キー・ハンドラの作成
		KeyHandler keyHandler = new KeyHandler();

		// DELキーと削除アクションを結びつける
		keyHandler.put(KeyStroke.getPressed(SWT.DEL, 127, 0),
				getActionRegistry().getAction(ActionFactory.DELETE.getId()));

		// F2キーとDirectEditActionを結びつける
		keyHandler.put(KeyStroke.getPressed(SWT.F2, 0), getActionRegistry()
				.getAction(GEFActionConstants.DIRECT_EDIT));

		// グラフィカル・ビューワにキー・ハンドラを設定
		getGraphicalViewer().setKeyHandler(keyHandler);

		// キー・ハンドラについては以下のようにすれば、
		// カーソル・キーによる選択の移動も可能になります。
		// グラフィカル・ビューワにキー・ハンドラを設定
		getGraphicalViewer().setKeyHandler(
				new GraphicalViewerKeyHandler(getGraphicalViewer())
						.setParent(keyHandler));
	}

	/**
	 * アクションを定義する。
	 * 
	 * @see org.eclipse.gef.ui.parts.GraphicalEditor#createActions()
	 */
	protected void createActions() {
		super.createActions();
		ActionRegistry registry = getActionRegistry();

		IAction action = new DirectEditAction((IWorkbenchPart) this);
		registry.registerAction(action);

		// だんだんわからなくなってきました
		// 選択オブジェクトによってアクションを更新する必要がある場合には
		// 以下のようにして、そのアクションのIDを登録しておく
		getSelectionActions().add(action.getId());

		// 水平方向の整列アクション
		action = new AlignmentAction((IWorkbenchPart) this,
				PositionConstants.LEFT);
		registry.registerAction(action);
		getSelectionActions().add(action.getId());

		action = new AlignmentAction((IWorkbenchPart) this,
				PositionConstants.CENTER);
		registry.registerAction(action);
		getSelectionActions().add(action.getId());

		action = new AlignmentAction((IWorkbenchPart) this,
				PositionConstants.RIGHT);
		registry.registerAction(action);
		getSelectionActions().add(action.getId());

		// 垂直方向の整列アクション
		action = new AlignmentAction((IWorkbenchPart) this,
				PositionConstants.TOP);
		registry.registerAction(action);
		getSelectionActions().add(action.getId());

		action = new AlignmentAction((IWorkbenchPart) this,
				PositionConstants.MIDDLE);
		registry.registerAction(action);
		getSelectionActions().add(action.getId());

		action = new AlignmentAction((IWorkbenchPart) this,
				PositionConstants.BOTTOM);
		registry.registerAction(action);
		getSelectionActions().add(action.getId());

	}

	/**
	 * @param LaxView
	 *            LaxView を設定。
	 */
	public void setLaxView(GraphicalViewer laxView) {
		this.laxView = laxView;
	}
}