/*
 * Created on Jan 17, 2005
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package org.eclipse.jst.j2ee.internal;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.jar.Manifest;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.util.URI;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jem.util.logger.proxy.Logger;
import org.eclipse.jem.workbench.utility.JemProjectUtilities;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.IPreferencePage;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jst.common.componentcore.util.ComponentUtilities;
import org.eclipse.jst.j2ee.application.internal.operations.ClassPathSelection;
import org.eclipse.jst.j2ee.application.internal.operations.ClasspathElement;
import org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.ArchiveManifest;
import org.eclipse.jst.j2ee.commonarchivecore.internal.helpers.ArchiveManifestImpl;
import org.eclipse.jst.j2ee.internal.common.ClasspathModel;
import org.eclipse.jst.j2ee.internal.common.ClasspathModelEvent;
import org.eclipse.jst.j2ee.internal.common.ClasspathModelListener;
import org.eclipse.jst.j2ee.internal.common.operations.UpdateJavaBuildPathOperation;
import org.eclipse.jst.j2ee.internal.listeners.IValidateEditListener;
import org.eclipse.jst.j2ee.internal.listeners.ValidateEditListener;
import org.eclipse.jst.j2ee.internal.project.J2EEComponentUtilities;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.dialogs.PropertyPage;
import org.eclipse.wst.common.componentcore.ComponentCore;
import org.eclipse.wst.common.componentcore.ModuleCoreNature;
import org.eclipse.wst.common.componentcore.UnresolveableURIException;
import org.eclipse.wst.common.componentcore.internal.impl.ModuleURIUtil;
import org.eclipse.wst.common.componentcore.internal.util.IModuleConstants;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.eclipse.wst.common.componentcore.resources.IVirtualReference;
import org.eclipse.wst.common.frameworks.internal.ui.WTPUIPlugin;
import org.eclipse.wst.common.frameworks.internal.ui.WorkspaceModifyComposedOperation;

/**
 * @author jialin
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
public class JARDependencyPropertiesPage extends PropertyPage implements IClasspathTableOwner, Listener, ClasspathModelListener, ICommonManifestUIConstants {

    protected IProject project;
    protected IOException caughtManifestException;
    protected boolean isDirty;
    protected Text classPathText;
    protected Text componentNameText;
    protected ClasspathModel model;
    protected CCombo availableAppsCombo;
    protected ClasspathTableManager tableManager;
    protected IValidateEditListener validateEditListener;
    protected Label manifestLabel;
    protected Label enterpriseApplicationLabel;
    protected Label availableDependentJars;
  

    /**
	 * Constructor for JARDependencyPropertiesPage.
	 */
    public JARDependencyPropertiesPage() {
        super();
    }

    protected void initialize() {
        project = (IProject) getElement().getAdapter(IResource.class);
        model = new ClasspathModel(null);
        model.setProject(project);
        if( model.getComponent() != null ){
	        model.addListener(this);
	        updateModelManifest();
	        initializeValidateEditListener();
        }
    }
    
    public void dispose() {
    	super.dispose();
    	if(model.earArtifactEdit != null) {
    		model.earArtifactEdit.dispose();
    		model.earArtifactEdit = null;
    	}
    }

    private void updateModelManifest() {
        if (JemProjectUtilities.isBinaryProject(project) || model.getAvailableEARComponents().length == 0)
            return;
        IContainer root = null;
        IFile manifestFile = null;
        if (project != null)
            root = project;
        else
            root = JemProjectUtilities.getSourceFolderOrFirst(project, null);

        if (root != null)
            manifestFile = root.getFile(new Path(J2EEConstants.MANIFEST_URI));

        if (manifestFile == null || !manifestFile.exists())
            return;

        InputStream in = null;
        try {
            in = manifestFile.getContents();
            ArchiveManifest mf = new ArchiveManifestImpl(new Manifest(in));
            model.primSetManifest(mf);
        } catch (CoreException e) {
            Logger.getLogger().logError(e);
            model.primSetManifest(new ArchiveManifestImpl());
        } catch (IOException iox) {
            Logger.getLogger().logError(iox);
            model.primSetManifest(new ArchiveManifestImpl());
            caughtManifestException = iox;
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException weTried) {
                	//Ignore
                }
            }
        }
    }

    protected void initializeValidateEditListener() {
        validateEditListener = new ValidateEditListener(null, model);
        validateEditListener.setShell(getShell());
    }

    /**
	 * @see org.eclipse.jface.dialogs.IDialogPage#setVisible(boolean)
	 */
    public void setVisible(boolean visible) {
        super.setVisible(visible);
        if (visible && caughtManifestException != null && !model.isDirty())
            ManifestErrorPrompter.showManifestException(getShell(), ERROR_READING_MANIFEST_DIALOG_MESSAGE_PROP_PAGE, false, caughtManifestException);

    }

    /**
	 * @see PreferencePage#createContents(Composite)
	 */
    protected Control createContents(Composite parent) {
        initialize();

        Composite composite = createBasicComposite(parent);
        GridLayout layout = new GridLayout();
        layout.marginWidth = 0;
        layout.marginWidth = 0;
        composite.setLayout(layout);
        composite.setLayoutData(new GridData(GridData.FILL_BOTH));
        if( model.getComponent() != null ){        
	        if(!isValidComponent())
	        	return composite;
	        createProjectLabelsGroup(composite);
	        createListGroup(composite);
	        createTextGroup(composite);
	        refresh();
    	}
        return composite;
    }
	
	/**
	 * @param comp
	 * @return
	 */
	protected Composite createBasicComposite(Composite comp) {
		Composite composite = new Composite(comp, SWT.NONE);
		GridLayout layout = new GridLayout();
        layout.marginWidth = 0;
        layout.marginWidth = 0;
        composite.setLayout(layout);
        composite.setLayoutData(new GridData(GridData.FILL_BOTH));
		return composite;
	}

	protected boolean isValidComponent() {
		if (model.getComponent().getComponentTypeId().equals(IModuleConstants.JST_EAR_MODULE)) {
			this.setErrorMessage(ManifestUIResourceHandler.getString("EAR_Module_Dep_Error")); //$NON-NLS-1$
			return false;
		} else if (J2EEComponentUtilities.isStandaloneComponent(model.getComponent()) ) {
			this.setErrorMessage(ClasspathModel.NO_EAR_MESSAGE);
			return false;
		}
		return true;
	}

    protected void createProjectLabelsGroup(Composite parent) {

		Composite labelsGroup = new Composite(parent, SWT.NONE);
		GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		labelsGroup.setLayout(layout);
		labelsGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		Label label = new Label(labelsGroup, SWT.NONE);
		label.setText(ManifestUIResourceHandler.getString("Project_name__UI_")); //$NON-NLS-1$ = "Project name:"

		componentNameText = new Text(labelsGroup, SWT.BORDER);
		GridData data = new GridData(GridData.FILL_HORIZONTAL);
		componentNameText.setEditable(false);
		componentNameText.setLayoutData(data);
		componentNameText.setText(project.getName());
		
		createEnterpriseAppsControls(labelsGroup);

	}

    private void createEnterpriseAppsControls(Composite labelsGroup) {

		enterpriseApplicationLabel = new Label(labelsGroup, SWT.NONE);
		enterpriseApplicationLabel.setText(ManifestUIResourceHandler.getString("EAR_Project_Name__UI__UI_")); //$NON-NLS-1$ = "EAR project name:"

		availableAppsCombo = new CCombo(labelsGroup, SWT.READ_ONLY | SWT.BORDER);
		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
		availableAppsCombo.setLayoutData(gd);

		availableAppsCombo.addListener(SWT.Selection, this);

	}
    
    protected void createListGroup(Composite parent) {
        Composite listGroup = new Composite(parent, SWT.NONE);
        GridLayout layout = new GridLayout();
        layout.numColumns = 1;
        layout.marginWidth = 0;
        layout.marginHeight = 0;
        listGroup.setLayout(layout);
        GridData gData = new GridData(GridData.FILL_BOTH);
        gData.horizontalIndent = 5;
        listGroup.setLayoutData(gData);

        availableDependentJars = new Label(listGroup, SWT.NONE);
        gData = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL);
        availableDependentJars.setText(ManifestUIResourceHandler.getString("Available_dependent_JARs__UI_")); //$NON-NLS-1$ = "Available dependent JARs:"
        availableDependentJars.setLayoutData(gData);
        createTableComposite(listGroup);
    }

    /*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.etools.j2ee.common.ui.classpath.IClasspathTableOwner#createGroup(org.eclipse.swt.widgets.Composite)
	 */
    public Group createGroup(Composite parent) {
        return new Group(parent, SWT.NULL);
    }

    protected void createTextGroup(Composite parent) {

		Composite textGroup = new Composite(parent, SWT.NONE);
		GridLayout layout = new GridLayout();
		layout.numColumns = 1;
		textGroup.setLayout(layout);
		textGroup.setLayoutData(new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL));

		createClassPathText(textGroup);

	}

    protected void createClassPathText(Composite textGroup) {
    	
    	manifestLabel = new Label(textGroup, SWT.NONE);
		manifestLabel.setText(ManifestUIResourceHandler.getString("Manifest_Class-Path__UI_")); //$NON-NLS-1$ = "Manifest Class-Path:"
		
        classPathText = new Text(textGroup, SWT.BORDER | SWT.MULTI | SWT.WRAP | SWT.V_SCROLL);
        GridData gData = new GridData(GridData.FILL_BOTH);
        gData.widthHint = 400;
        gData.heightHint = 100;
        classPathText.setLayoutData(gData);
        classPathText.setEditable(false);
    }
    
    protected void createTableComposite(Composite parent) {
        Composite composite = new Composite(parent, SWT.NONE);
        GridData gData = new GridData(GridData.FILL_BOTH);
        composite.setLayoutData(gData);
        tableManager = new ClasspathTableManager(this, model, validateEditListener);
        tableManager.setReadOnly(isReadOnly());
        tableManager.fillComposite(composite);
    }

    /**
	 * @see IClasspathTableOwner#createAvailableJARsViewer(Composite)
	 */
    public CheckboxTableViewer createAvailableJARsViewer(Composite parent) {
        int flags = SWT.CHECK | SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI;

        Table table = new Table(parent,flags);
        CheckboxTableViewer availableJARsViewer = new CheckboxTableViewer(table);

        // set up table layout
        TableLayout tableLayout = new org.eclipse.jface.viewers.TableLayout();
        tableLayout.addColumnData(new ColumnWeightData(200, true));
        tableLayout.addColumnData(new ColumnWeightData(200, true));
        table.setLayout(tableLayout);
        table.setHeaderVisible(true);
        table.setLinesVisible(true);
        availableJARsViewer.setSorter(null);

        // table columns
        TableColumn fileNameColumn = new TableColumn(table, SWT.NONE, 0);
        fileNameColumn.setText(ManifestUIResourceHandler.getString("JAR/Module_UI_")); //$NON-NLS-1$
        fileNameColumn.setResizable(true);

        TableColumn projectColumn = new TableColumn(table, SWT.NONE, 1);
        projectColumn.setText(ManifestUIResourceHandler.getString("Project_UI_")); //$NON-NLS-1$ = "Project"
        projectColumn.setResizable(true);
        tableLayout.layout(table, true);
        return availableJARsViewer;

    }

    /**
	 * @see IClasspathTableOwner#createButtonColumnComposite(Composite)
	 */
    public Composite createButtonColumnComposite(Composite parent) {
        Composite buttonColumn = new Composite(parent, SWT.NONE);
        GridLayout layout = new GridLayout();
        layout.numColumns = 1;
        layout.marginHeight = 0;
        layout.marginWidth = 0;
        buttonColumn.setLayout(layout);
        GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_BEGINNING);
        buttonColumn.setLayoutData(data);
        return buttonColumn;
    }

    /**
	 * @see IClasspathTableOwner
	 */
    public Button primCreatePushButton(String label, Composite buttonColumn) {
        Button aButton = new Button(buttonColumn, SWT.PUSH);
        aButton.setText(label);
        return aButton;
    }

    /**
	 * @see IClasspathTableOwner
	 */
    public Button primCreateRadioButton(String label, Composite parent) {
        Button aButton = new Button(parent, SWT.RADIO);
        aButton.setText(label);
        return aButton;
    }

    /**
	 * @see Listener#handleEvent(Event)
	 */
    public void handleEvent(Event event) {
        if (event.widget == availableAppsCombo)
            availableAppsSelected(event);
    }
    
	protected void availableAppsSelected(Event event) {
        int index = availableAppsCombo.getSelectionIndex();
        model.selectEAR(index);
    }
    protected void populateApps() {
		IVirtualComponent[] components = model.getAvailableEARComponents();
		String[] values = new String[components.length];
		for (int i = 0; i < components.length; i++) {
			values[i] = components[i].getProject().getName();
		}
		if (availableAppsCombo != null) {
			availableAppsCombo.setItems(values);
			IVirtualComponent selected = model.getSelectedEARComponent();
			if (selected != null) {
				int index = Arrays.asList(components).indexOf(selected);
				availableAppsCombo.select(index);
			} else
				availableAppsCombo.clearSelection();
		}
	}

    protected void refresh() {
		populateApps();
		tableManager.refresh();
		refreshText();
	}
    

    public void refreshText() {
		ClassPathSelection sel = model.getClassPathSelection();
		if( sel != null && classPathText != null )
			classPathText.setText(sel == null ? "" : sel.toString()); //$NON-NLS-1$
	}

    /**
	 * @see ClasspathModelListener#modelChanged(ClasspathModelEvent)
	 */
    public void modelChanged(ClasspathModelEvent evt) {
        if (evt.getEventType() == ClasspathModelEvent.CLASS_PATH_CHANGED) {
            isDirty = true;
            refreshText();
        } else if (evt.getEventType() == ClasspathModelEvent.EAR_PROJECT_CHANGED)
            tableManager.refresh();
    }

    /**
	 * @see PreferencePage#performDefaults()
	 */
    protected void performDefaults() {
        model.resetClassPathSelection();
        refresh();
        isDirty = false;
        model.dispose();
    }
    
    public boolean performCancel() {
    	model.dispose();
    	return super.performCancel();
    }

    /**
	 * @see IPreferencePage#performOk() 
	 */
    public boolean performOk() {
        if (!isDirty)
            return true;
        WorkspaceModifyComposedOperation composed = new WorkspaceModifyComposedOperation(createManifestOperation());
        composed.addRunnable(createBuildPathOperation());
        try {
            new ProgressMonitorDialog(getShell()).run(true, true, composed);
        } catch (InvocationTargetException ex) {
            String title = ManifestUIResourceHandler.getString("An_internal_error_occurred_ERROR_"); //$NON-NLS-1$
            String msg = title;
            if (ex.getTargetException() != null && ex.getTargetException().getMessage() != null)
                msg = ex.getTargetException().getMessage();
            MessageDialog.openError(this.getShell(), title, msg);
            org.eclipse.jem.util.logger.proxy.Logger.getLogger().logError(ex);
            return false;
        } catch (InterruptedException e) {
            // cancelled
            return false;
        } finally {
        	model.dispose();
        }
        isDirty = false;
        return true;
    }
    
//    private boolean runWLPOp(WorkspaceModifyComposedOperation composed) {
//    	try {
//			if (composed != null)
//				new ProgressMonitorDialog(getShell()).run(true, true, composed);
//		} catch (InvocationTargetException ex) {
//			String title = ManifestUIResourceHandler.getString("An_internal_error_occurred_ERROR_"); //$NON-NLS-1$
//			String msg = title;
//			if (ex.getTargetException() != null && ex.getTargetException().getMessage() != null)
//				msg = ex.getTargetException().getMessage();
//			MessageDialog.openError(this.getShell(), title, msg);
//			org.eclipse.jem.util.logger.proxy.Logger.getLogger().logError(ex);
//			return false;
//		} catch (InterruptedException e) {
//			// cancelled
//			return false;
//		}
//		return true;
//    }

	protected WorkspaceModifyComposedOperation createComponentDependencyOperations() {
		WorkspaceModifyComposedOperation composedOp = null;
		List selected = getSelectedClassPathSelectionForWLPs().getClasspathElements();
		List unselected = getUnSelectedClassPathSelectionForWLPs().getClasspathElements();
		
		List targetComponentsHandles = new ArrayList();
		for (int i = 0; i < selected.size(); i++) {
			ClasspathElement element = (ClasspathElement) selected.get(i);
			IProject elementProject = element.getProject();
			if( elementProject != null ){
				IVirtualComponent targetComp = ComponentCore.createComponent(elementProject);
				targetComponentsHandles.add(targetComp);
			}
		}
		if (!targetComponentsHandles.isEmpty()) {
			composedOp = new WorkspaceModifyComposedOperation();
			composedOp.addRunnable(WTPUIPlugin.getRunnableWithProgress(ComponentUtilities.createWLPReferenceComponentOperation(model.getComponent(), targetComponentsHandles)));
		}
		targetComponentsHandles = new ArrayList();
		for (int i = 0; i < unselected.size(); i++) {
			ClasspathElement element = (ClasspathElement) unselected.get(i);
			IProject elementProject = element.getProject();
			if( elementProject != null ){
				if (ModuleCoreNature.isFlexibleProject(elementProject)) {
					IVirtualComponent targetComp = ComponentCore.createComponent(elementProject);
					targetComponentsHandles.add(targetComp);
				}
			}else{
				URI archiveURI = element.getArchiveURI();
				if( archiveURI != null && !archiveURI.equals("") ){ //$NON-NLS-1$
					String name = ""; //$NON-NLS-1$
					try {
						String type = ModuleURIUtil.getArchiveType(archiveURI);
						String tmpname = ModuleURIUtil.getArchiveName(archiveURI);
						name = type + IPath.SEPARATOR + tmpname;
					} catch (UnresolveableURIException e) {
						Logger.getLogger().logError(e.getMessage());
					}
					if( !name.equals("")){ //$NON-NLS-1$
						IVirtualReference ref = model.getComponent().getReference(name);
						IVirtualComponent referenced = ref.getReferencedComponent();
						targetComponentsHandles.add(referenced);
					}	
				}
			}
		}
		if (!targetComponentsHandles.isEmpty()) {
			if(composedOp == null)
				composedOp = new WorkspaceModifyComposedOperation();
			composedOp.addRunnable(WTPUIPlugin.getRunnableWithProgress(ComponentUtilities.removeReferenceComponentOperation(model.getComponent(), targetComponentsHandles)));
		}
		return composedOp;
	}
	
	protected WorkspaceModifyComposedOperation createFlexProjectOperations() {
		WorkspaceModifyComposedOperation composedOp = null;
		try {
			Object[] elements = tableManager.availableJARsViewer.getCheckedElements();
			for (int i = 0; i < elements.length; i++) {
				ClasspathElement element = (ClasspathElement) elements[i];
				IProject elementProject = element.getProject();
				if ( elementProject != null && !elementProject.hasNature(IModuleConstants.MODULE_NATURE_ID)) {
					if(composedOp == null)
						composedOp = new WorkspaceModifyComposedOperation();
					composedOp.addRunnable(WTPUIPlugin.getRunnableWithProgress(ComponentUtilities.createFlexJavaProjectForProjectOperation(elementProject)));
				}
			}
		} catch (CoreException ce) {
		}
		return composedOp;
	}
	
	protected IRunnableWithProgress createBuildPathOperation() {
        IJavaProject javaProject = JemProjectUtilities.getJavaProject(project);
        return WTPUIPlugin.getRunnableWithProgress(new UpdateJavaBuildPathOperation(javaProject,getSelectedClassPathSelectionForWLPs()));
    }
	
	protected IRunnableWithProgress createWLPBuildPathOperation() {
        IJavaProject javaProject = JemProjectUtilities.getJavaProject(project);
        return WTPUIPlugin.getRunnableWithProgress(new UpdateJavaBuildPathOperation(javaProject,getSelectedClassPathSelectionForWLPs(),getUnSelectedClassPathSelectionForWLPs()));
    }
	
	protected ClassPathSelection getUnSelectedClassPathSelectionForWLPs() {
		ClassPathSelection selection = new ClassPathSelection();
		Object[] checkedElements = tableManager.availableJARsViewer.getCheckedElements();
		List modelElements = model.getClassPathSelectionForWLPs().getClasspathElements();
		for (int i = 0; i < modelElements.size(); i++) {
			List checkedElementsList = Arrays.asList(checkedElements);
			if (!checkedElementsList.contains(modelElements.get(i))) {
				selection.getClasspathElements().add(modelElements.get(i));
			}
		}
		return selection;
	}
	
    
    private ClassPathSelection getSelectedClassPathSelectionForWLPs() {
    		ClassPathSelection selection = new ClassPathSelection();
    		Object[] checkedElements = tableManager.availableJARsViewer.getCheckedElements();
    		for(int i = 0; i < checkedElements.length; i++) {
    			selection.getClasspathElements().add(checkedElements[i]);
    		}
    		return selection;
	}
    
    protected UpdateManifestOperation createManifestOperation() {
        return new UpdateManifestOperation(project.getName(), model.getClassPathSelection().toString(), true);
    }

    protected boolean isReadOnly() {
        return JemProjectUtilities.isBinaryProject(project);
    }

}