/*******************************************************************************
 * Copyright (c) 2004, 2007 QNX Software Systems 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:
 *     QNX Software Systems - initial API and implementation
 *     Anton Leherbauer (Wind River Systems)
 *     Sergey Prigogin (Google)
 *******************************************************************************/
package org.eclipse.cdt.internal.ui.wizards.filewizard;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.text.templates.Template;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Text;

import org.eclipse.cdt.core.CConventions;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.ui.CodeGeneration;

import org.eclipse.cdt.internal.corext.codemanipulation.StubUtility;

import org.eclipse.cdt.internal.ui.dialogs.StatusInfo;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.DialogField;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.LayoutUtil;
import org.eclipse.cdt.internal.ui.wizards.dialogfields.StringDialogField;

public class NewSourceFileCreationWizardPage extends AbstractFileCreationWizardPage {
	private final String KEY_LAST_USED_TEMPLATE = "LastUsedSourceTemplate"; //$NON-NLS-1$

	private ITranslationUnit fNewFileTU = null;
	private StringDialogField fNewFileDialogField;
	
	public NewSourceFileCreationWizardPage() {
		super(NewFileWizardMessages.NewSourceFileCreationWizardPage_title); 
		setDescription(NewFileWizardMessages.NewSourceFileCreationWizardPage_description); 

		fNewFileDialogField = new StringDialogField();
		fNewFileDialogField.setDialogFieldListener(new IDialogFieldListener() {
			public void dialogFieldChanged(DialogField field) {
				handleFieldChanged(NEW_FILE_ID);
			}
		});
		fNewFileDialogField.setLabelText(NewFileWizardMessages.NewSourceFileCreationWizardPage_sourceFile_label); 
	}
	
	/**
	 * Sets the focus on the starting input field.
	 */
	@Override
	protected void setFocus() {
		fNewFileDialogField.setFocus();
	}

	/**
	 * Creates the controls for the file name field. Expects a <code>GridLayout</code> with at 
	 * least 2 columns.
	 * 
	 * @param parent the parent composite
	 * @param nColumns number of columns to span
	 */		
	@Override
	protected void createFileControls(Composite parent, int nColumns) {
		fNewFileDialogField.doFillIntoGrid(parent, nColumns);
		Text textControl = fNewFileDialogField.getTextControl(null);
		LayoutUtil.setWidthHint(textControl, getMaxFieldWidth());
		textControl.addFocusListener(new StatusFocusListener(NEW_FILE_ID));
	}
	
	@Override
	public IPath getFileFullPath() {
		String str = fNewFileDialogField.getText();
        IPath path = null;
	    if (str.length() > 0) {
	        path = new Path(str);
	        if (!path.isAbsolute()) {
	            IPath folderPath = getSourceFolderFullPath();
	        	if (folderPath != null)
	        	    path = folderPath.append(path);
	        }
	    }
	    return path;
	}
	
	@Override
	protected IStatus fileNameChanged() {
		StatusInfo status = new StatusInfo();
		
		IPath filePath = getFileFullPath();
		if (filePath == null) {
			status.setError(NewFileWizardMessages.NewSourceFileCreationWizardPage_error_EnterFileName); 
			return status;
		}

		IPath sourceFolderPath = getSourceFolderFullPath();
		if (sourceFolderPath == null || !sourceFolderPath.isPrefixOf(filePath)) {
			status.setError(NewFileWizardMessages.NewSourceFileCreationWizardPage_error_FileNotInSourceFolder); 
			return status;
		}
		
		// check if file already exists
		IResource file = getWorkspaceRoot().findMember(filePath);
		if (file != null && file.exists()) {
	    	if (file.getType() == IResource.FILE) {
	    		status.setError(NewFileWizardMessages.NewSourceFileCreationWizardPage_error_FileExists); 
	    	} else if (file.getType() == IResource.FOLDER) {
	    		status.setError(NewFileWizardMessages.NewSourceFileCreationWizardPage_error_MatchingFolderExists); 
	    	} else {
	    		status.setError(NewFileWizardMessages.NewSourceFileCreationWizardPage_error_MatchingResourceExists); 
	    	}
			return status;
		}
		
		// check if folder exists
		IPath folderPath = filePath.removeLastSegments(1).makeRelative();
		IResource folder = getWorkspaceRoot().findMember(folderPath);
		if (folder == null || !folder.exists() || (folder.getType() != IResource.PROJECT && folder.getType() != IResource.FOLDER)) {
		    status.setError(NLS.bind(NewFileWizardMessages.NewSourceFileCreationWizardPage_error_FolderDoesNotExist, folderPath)); 
			return status;
		}

		IStatus convStatus = CConventions.validateSourceFileName(getCurrentProject(), filePath.lastSegment());
		if (convStatus.getSeverity() == IStatus.ERROR) {
			status.setError(NLS.bind(NewFileWizardMessages.NewSourceFileCreationWizardPage_error_InvalidFileName, convStatus.getMessage())); 
			return status;
		} else if (convStatus.getSeverity() == IStatus.WARNING) {
			status.setWarning(NLS.bind(NewFileWizardMessages.NewSourceFileCreationWizardPage_warning_FileNameDiscouraged, convStatus.getMessage())); 
		}
		return status;
	}
	
	@Override
	public void createFile(IProgressMonitor monitor) throws CoreException {
        IPath filePath = getFileFullPath();
        if (filePath != null) {
            if (monitor == null)
	            monitor = new NullProgressMonitor();
            try {
	            fNewFileTU = null;
	            IFile newFile = NewSourceFileGenerator.createSourceFile(filePath, true, monitor);
	            if (newFile != null) {
	            	fNewFileTU = (ITranslationUnit) CoreModel.getDefault().create(newFile);
	            	if (fNewFileTU != null) {
	            		String lineDelimiter= StubUtility.getLineDelimiterUsed(fNewFileTU);
						String content= CodeGeneration.getBodyFileContent(getTemplate(), fNewFileTU, null, null, lineDelimiter);
						if (content != null) {
							fNewFileTU.getBuffer().setContents(content.toCharArray());
							fNewFileTU.save(monitor, true);
						}
	            	}
	            }
	        } finally {
	            monitor.done();
	        }
        }
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.internal.ui.wizards.filewizard.AbstractFileCreationWizardPage#getCreatedFileTU()
	 */
	@Override
	public ITranslationUnit getCreatedFileTU() {
		return fNewFileTU;
	}

	/*
	 * @see org.eclipse.cdt.internal.ui.wizards.filewizard.AbstractFileCreationWizardPage#getApplicableTemplates()
	 */
	@Override
	protected Template[] getApplicableTemplates() {
		return StubUtility.getFileTemplatesForContentTypes(
				new String[] { CCorePlugin.CONTENT_TYPE_CXXSOURCE, CCorePlugin.CONTENT_TYPE_CSOURCE }, null);
	}
	
	/*
	 * @see org.eclipse.cdt.internal.ui.wizards.filewizard.AbstractFileCreationWizardPage#getPreferredTemplateName()
	 */
	@Override
	public String getLastUsedTemplateName() {
		return getDialogSettings().get(KEY_LAST_USED_TEMPLATE);
	}
	
	/*
	 * @see org.eclipse.cdt.internal.ui.wizards.filewizard.AbstractFileCreationWizardPage#savePreferredTemplateName(String)
	 */
	@Override
	public void saveLastUsedTemplateName(String name) {
		getDialogSettings().put(KEY_LAST_USED_TEMPLATE, name);
	}
}
