/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.sling.ide.eclipse.ui.wizards;

import static org.apache.sling.ide.eclipse.core.progress.ProgressUtils.advance;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.apache.sling.ide.eclipse.core.ConfigurationHelper;
import org.apache.sling.ide.eclipse.core.DefaultSlingLaunchpadConfiguration;
import org.apache.sling.ide.eclipse.core.ISlingLaunchpadConfiguration;
import org.apache.sling.ide.eclipse.ui.WhitelabelSupport;
import org.apache.sling.ide.eclipse.ui.internal.Activator;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
import org.eclipse.wst.server.core.IModule;
import org.eclipse.wst.server.core.IServer;
import org.eclipse.wst.server.core.IServerWorkingCopy;
import org.eclipse.wst.server.core.ServerUtil;

/**
 * The <tt>AbstractNewSlingApplicationWizard</tt> is a support class for wizards which create Sling applications
 *
 */
public abstract class AbstractNewSlingApplicationWizard extends Wizard implements INewWizard {

    private SetupServerWizardPage setupServerWizardPage = new SetupServerWizardPage(this);

    public void init(IWorkbench workbench, IStructuredSelection selection) {
    }

    /**
     * 
     * @return the current wizard page, possibly null
     */
    protected WizardPage getCurrentWizardPage() {
        IWizardPage currentPage = getContainer().getCurrentPage();
        if (currentPage instanceof WizardPage) {
            return (WizardPage) currentPage;
        }

        return null;
    }

    public void reportError(CoreException e) {
        WizardPage currentPage = getCurrentWizardPage();
        if (currentPage != null) {
            currentPage.setMessage(e.getMessage(), IMessageProvider.ERROR);
        } else {
            MessageDialog.openError(getShell(), "Unexpected error", e.getMessage());
        }

        Activator.getDefault().getLog().log(e.getStatus());
    }

    public void reportError(Throwable t) {
        if (t instanceof CoreException) {
            reportError((CoreException) t);
            return;
        }

        IStatus status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, t.getMessage(), t);
        reportError(new CoreException(status));
    }

    protected SetupServerWizardPage getSetupServerWizardPage() {
        return setupServerWizardPage;
    }
    /**
     * This method is called when 'Finish' button is pressed in the wizard. We will create an operation and run it using
     * wizard as execution context.
     */
    public boolean performFinish() {

        try {
            // create projects
            final List<IProject> createdProjects = new ArrayList<>();
            getContainer().run(false, true, new WorkspaceModifyOperation() {
                @Override
                protected void execute(IProgressMonitor monitor) throws CoreException, InvocationTargetException,
                        InterruptedException {
                    createdProjects.addAll(createProjects(monitor));
                }
            });

            // configure projects
            final Projects[] projects = new Projects[1];
            getContainer().run(false, true, new WorkspaceModifyOperation() {
                @Override
                protected void execute(IProgressMonitor monitor) throws CoreException, InvocationTargetException,
                        InterruptedException {
                    projects[0] = configureCreatedProjects(createdProjects, monitor);
                }
            });

            // deploy the projects on server
            getContainer().run(false, true, new WorkspaceModifyOperation() {
                @Override
                protected void execute(IProgressMonitor monitor) throws CoreException, InvocationTargetException,
                        InterruptedException {
                    deployProjectsOnServer(projects[0], monitor);
                }
            });

            // ensure server is started and all modules are published
            getContainer().run(false, false, new IRunnableWithProgress() {

                @Override
                public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
                    try {
                        publishModules(createdProjects, monitor);
                    } catch (CoreException e) {
                        throw new InvocationTargetException(e);
                    }
                }
            });
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return false;
        } catch (InvocationTargetException e) {
            reportError(e.getTargetException());
            return false;
        }

        return true;
    }

    protected abstract List<IProject> createProjects(IProgressMonitor monitor) throws CoreException;

    protected abstract Projects configureCreatedProjects(List<IProject> createdProjects, IProgressMonitor monitor)
            throws CoreException;

    protected void deployProjectsOnServer(Projects projects, IProgressMonitor monitor) throws CoreException {

        IServer server = setupServerWizardPage.getOrCreateServer(monitor);
        if (server == null) {
            monitor.done();
            return;
        }
        advance(monitor, 1);

        IServerWorkingCopy wc = server.createWorkingCopy();
        // add the bundle and content projects, ie modules, to the server
        List<IModule> modules = new LinkedList<>();
        for (IProject project : projects.getBundleProjects()) {
            IModule module = ServerUtil.getModule(project);
            if (module != null && shouldDeploy(module)) {
                modules.add(module);
            }
        }
        for (IProject project : projects.getContentProjects()) {
            IModule module = ServerUtil.getModule(project);
            if (module != null && shouldDeploy(module)) {
                modules.add(module);
            }
        }
        wc.modifyModules(modules.toArray(new IModule[modules.size()]), new IModule[0], monitor);
        wc.save(true, monitor);

        advance(monitor, 2);

        monitor.done();
    }

    /**
     * Extension method to allow subclasses to deploy and publish specific modules created by the wizard
     * 
     * <p>
     * By default, all modules are deployed
     * 
     * @param module the module
     * @return true is the module should be deployed, false otherwise
     */
    protected boolean shouldDeploy(IModule module) {
        return true;
    }

    protected void publishModules(final List<IProject> createdProjects, IProgressMonitor monitor) throws CoreException {
        IServer server = setupServerWizardPage.getOrCreateServer(monitor);
        if (server == null) {
            return;
        }
        if (setupServerWizardPage.getStartServer()) {
            server.start(ILaunchManager.RUN_MODE, monitor);
        }
        List<IModule[]> modules = new ArrayList<>();
        for (IProject project : createdProjects) {
            IModule module = ServerUtil.getModule(project);
            if (module != null && shouldDeploy(module)) {
                modules.add(new IModule[] { module });
            }
        }

        if (modules.size() > 0) {
            server.publish(IServer.PUBLISH_CLEAN, modules, null, null);
        }
    }

    protected void configureBundleProject(IProject aBundleProject, List<IProject> projects, IProgressMonitor monitor)
            throws CoreException {
        ConfigurationHelper.convertToBundleProject(aBundleProject);
    }

    protected void configureContentProject(IProject aContentProject, List<IProject> projects, IProgressMonitor monitor)
            throws CoreException {
        ConfigurationHelper.convertToContentPackageProject(aContentProject, monitor, new Path("src/main/content/jcr_root"));
    }

    protected void configureReactorProject(IProject reactorProject, IProgressMonitor monitor) throws CoreException {
        // nothing to be done
    }

    protected void finishConfiguration(List<IProject> projects, IServer server, IProgressMonitor monitor)
            throws CoreException {
        // nothing to be done by default - hook for subclasses
    }

    public ImageDescriptor getLogo() {
        return WhitelabelSupport.getProjectWizardBanner();
    }

    public abstract String doGetWindowTitle();
    
    protected ISlingLaunchpadConfiguration getDefaultConfig() {
        return DefaultSlingLaunchpadConfiguration.INSTANCE;
    }
}