/**
 * プロジェクト名 laxIde
 * クラス名 LetsAjaxNewProjcetWizard.java
 * 作成日: 2007/05/28
 * 
 */
package jp.co.cybec.laxide.wizards;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;

import jp.co.cybec.laxide.util.LetsAjaxWizardUtil;
import lax.LetsAjaxActivator;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.ILog;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.IWizardContainer;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
import org.eclipse.ui.dialogs.WizardNewProjectCreationPage;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
import org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard;

/**
 * LAX用新規プロジェクト作成ウィザードクラス.
 * <p>
 * ファイル名：LetsAjaxNewProjcetWizard.java
 * </p>
 * 
 * @author nakamura 作成時刻：10:52:21
 * 
 */
public class LetsAjaxNewProjcetWizard extends Wizard implements INewWizard {
	/** プロジェクト作成ウィザードページ */
	private WizardNewProjectCreationPage pageCreateProject;

	/** プロジェクトのコンフィグオブジェクト */
	private IConfigurationElement configElement;

	public LetsAjaxNewProjcetWizard() {
		setWindowTitle("LET'S AJAX 新規プロジェクト作成ウィザード");
	}

	@Override
	public boolean performFinish() {
		boolean flag = false;
		// プロジェクト生成フォルダが指定されているか、どうかを判定する。
		final IProject projectHandle = pageCreateProject.getProjectHandle();
		URI projectURI = (!pageCreateProject.useDefaults()) ? pageCreateProject
				.getLocationURI() : null;
		IWorkspace workspace = ResourcesPlugin.getWorkspace();

		final IProjectDescription desc = workspace
				.newProjectDescription(projectHandle.getName());

		// プロジェクト詳細情報をセット
		desc.setLocationURI(projectURI);

		// ワークスペースへの処理を実行する。
		WorkspaceModifyOperation op = new WorkspaceModifyOperation() {
			protected void execute(IProgressMonitor monitor)
					throws CoreException {
				createProject(desc, projectHandle, monitor);
			}
		};

		IWizardContainer container = getContainer();
		try {
			container.run(true, true, op);
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		// ネイチャーの設定
		if (this.setNature(projectHandle)) {
			flag = true;
		}

		// デフォルト新規LAXファイルの生成
		if (this.createNewFile(projectHandle)) {
			flag = true;
		}

		return flag;
	}

	/**
	 * ワークスペースにプロジェクトフォルダを生成する。
	 * 
	 * @param description
	 * @param projectHandle
	 * @param monitor
	 * @throws CoreException
	 * @throws OperationCanceledException
	 */
	private boolean createProject(IProjectDescription description,
			IProject proj, IProgressMonitor monitor) throws CoreException,
			OperationCanceledException {
		try {

			monitor.beginTask("", 2000);
			// プロジェクトフォルダの生成
			proj.create(description, new SubProgressMonitor(monitor, 1000));

			if (monitor.isCanceled()) {
				throw new OperationCanceledException();
			}

			proj.open(IResource.BACKGROUND_REFRESH, new SubProgressMonitor(
					monitor, 1000));
			// プロジェクト内に必要なフォルダを生成する。
			return this.createFolders(proj);

		} catch (Exception e) {
			Plugin plugin = LetsAjaxActivator.getInstance();
			ILog log = plugin.getLog();
			log.log(new Status(IStatus.ERROR, LetsAjaxActivator.PLUGIN_ID, 0,
					"LAX新規プロジェクト作成エラー", e));
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * LAXプロジェクトのフォルダ構成を作成する。
	 * 
	 * @param projectHandle
	 */
	private boolean createFolders(IProject projectHandle) {
		try {
			// フォルダハンドルの作成
			IFolder folder = (IFolder) projectHandle.getFolder("html");
			// フォルダ作成
			folder.create(false, true, null);

			// フォルダハンドルの作成
			IFolder childFolder = (IFolder) projectHandle.getFolder("html/js");
			// フォルダ作成
			childFolder.create(false, true, null);

			// フォルダハンドルの作成
			IFolder childFolder2 = (IFolder) projectHandle
					.getFolder("html/css");
			// フォルダ作成
			childFolder2.create(false, true, null);

		} catch (CoreException cex) {
			Plugin plugin = LetsAjaxActivator.getInstance();
			ILog log = plugin.getLog();
			log.log(new Status(IStatus.ERROR, LetsAjaxActivator.PLUGIN_ID, 0,
					"LAX新規プロジェクトフォルダ作成エラー", cex));
			cex.printStackTrace();
			return false;
		}
		return true;
	}

	private boolean setNature(IProject projectHandle) {
		boolean flag = false;
		try {
			// -----------------
			// ネイチャーの設定
			// -----------------

			// プロジェクトの説明情報を扱うためのAPIを取得
			IProjectDescription description = projectHandle.getDescription();
			// 既に設定されているネイチャーのリスト取得
			String natures[] = description.getNatureIds();

			// 既にネイチャーが登録されている場合、ここで一旦削除する
			for (int i = 0; i < natures.length; i++) {
				String[] newNatuers = new String[natures.length - 1];
				System.arraycopy(natures, 0, newNatuers, 0, 1);
				System.arraycopy(natures, i + 1, newNatuers, i,
						natures.length - 1 - 1);
				// 説明情報のネイチャー設定を置き換える
				description.setNatureIds(newNatuers);
				// プロジェクトに説明情報を設定する
				projectHandle.setDescription(description, null);
			}

			// 新たにプロジェクト用のネイチャーを登録する
			String[] newNatures = new String[natures.length + 1];
			System.arraycopy(natures, 0, newNatures, 0, natures.length);
			newNatures[natures.length] = LetsAjaxNature.NATURE_ID;
			// 説明情報のネイチャー設定を置き換える
			description.setNatureIds(newNatures);
			// プロジェクトに説明情報を設定する
			projectHandle.setDescription(description, null);

			// パースペクティブ切り替え
			BasicNewProjectResourceWizard.updatePerspective(configElement);

		} catch (CoreException cex) {
			Plugin plugin = LetsAjaxActivator.getInstance();
			ILog log = plugin.getLog();
			log.log(new Status(IStatus.ERROR, LetsAjaxActivator.PLUGIN_ID, 0,
					"LAX新規プロジェクト作成エラー", cex));
			cex.printStackTrace();
			return false;
		}
		return flag;
	}

	/**
	 * プロジェクト作成時にファイルを作成する。
	 * 
	 * @param projectHandle
	 * @return
	 */
	private boolean createNewFile(IProject projectHandle) {

		try {
			File file = new File(projectHandle.getLocation().toString()
					+ "/newLax.lax");
			file.createNewFile();
			InputStream stream = new FileInputStream(projectHandle
					.getLocation().toString()
					+ "/newLax.lax");

			IFile newFile = projectHandle.getFile("newLax.lax");
			newFile.create(stream, true, null);
			// アクティブコントロールの変更
			IWorkbenchPage page = PlatformUI.getWorkbench()
					.getActiveWorkbenchWindow().getActivePage();
			// 作成したファイルをエディターで開く
			IDE.openEditor(page, newFile, true);

			// 作成したファイルに初期のレイアウトXMLを設定する。
			LetsAjaxWizardUtil util = new LetsAjaxWizardUtil();
			util.initLaxDataToFile(file);

			return true;
		} catch (PartInitException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (CoreException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return false;
	}

	/**
	 * Creates a file resource handle for the file with the given workspace
	 * path. This method does not create the file resource; this is the
	 * responsibility of <code>createFile</code>.
	 * 
	 * @param filePath
	 *            the path of the file resource to create a handle for
	 * @return the new file resource handle
	 * @see #createFile
	 */
	protected IFile createFileHandle(IPath filePath) {

		return IDEWorkbenchPlugin.getPluginWorkspace().getRoot().getFile(
				filePath);
	}

	/**
	 * 拡張機能初期化処理.
	 * <p>
	 * Eclipse標準の拡張機能初期化処理です.
	 * </p>
	 * 
	 * @param config
	 * @param propertyName
	 * @param data
	 * @throws org.eclipse.core.runtime.CoreException
	 * @see {@link org.eclipse.core.runtime.IExecutableExtension#setInitializationData(IConfigurationElement, String, Object)}
	 */
	public void setInitializationData(IConfigurationElement config,
			String propertyName, Object data) throws CoreException {
		// パースペクティブ切り替えで使用するコンフィグ情報を取得しておく
		configElement = config;
	}

	/**
	 * 初期処理.
	 * 
	 * @param workbench
	 * @param selection
	 * @see org.eclipse.ui.IWorkbenchWizard#init(IWorkbench,
	 *      IStructuredSelection)
	 */
	public void init(IWorkbench workbench, IStructuredSelection selection) {
		// 処理なし
		// 非同期処理を行う場合など、ここでプログレスモニタ表示を行ってください
		setNeedsProgressMonitor(true);
	}

	/**
	 * ワークスペースにウィザードオブジェクトを設定します.
	 * 
	 * <p>
	 * ウィザードを生成して、Eclipseのワークスペースに出力します。
	 * </p>
	 * 
	 * @see org.eclipse.jface.wizard.Wizard#addPages()
	 */
	public void addPages() {

		// ウィザード・ページの作成
		pageCreateProject = new WizardNewProjectCreationPage("LET'S AJAX");
		// ページ・タイトルの設定
		pageCreateProject.setTitle("プロジェクト名の入力");
		// ページ・タイトルの下に表示される説明文
		pageCreateProject.setDescription("新規作成するLET'S AJAXプロジェクト名を入力して下さい");
		// ページの追加
		addPage(pageCreateProject);
	}

	/**
	 * 終了ボタン押下時正常判定.
	 * 
	 * <p>
	 * 終了ボタンが押下された場合のバリデーションを実装します。
	 * </p>
	 * 
	 * @return boolean ウィザードｎ入力が正しく完了している場合は<code>true</code>を、そうでない場合は<code>false</code>を返します
	 * @see org.eclipse.jface.wizard.Wizard#canFinish()
	 */
	public boolean canFinish() {

		// ページの入力が完了しているかどうか
		return pageCreateProject.isPageComplete();
	}
}
