/*******************************************************************************
 * Copyright (c) 2018 Red Hat, Inc.
 * Distributed under license by Red Hat, Inc. All rights reserved.
 * This program is 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:
 *   Red Hat, Inc. - initial API and implementation
 ******************************************************************************/
package org.jboss.tools.windup.core.test;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import org.jboss.tools.test.util.TestProjectProvider;
import org.jboss.tools.windup.core.IWindupListener;
import org.jboss.tools.windup.core.WindupCorePlugin;
import org.jboss.tools.windup.core.services.WindupService;
import org.junit.After;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;

/**
 * <p>
 * Tests for the {@link WindupService}.
 * </p>
 */
public class WindupServiceTest extends WindupTest
{
	
    @After
    public void cleanUpGeneratedReports() throws IOException, InterruptedException
    {
        // delete any reports generated by the test
        System.gc();
        File reportsDir = WindupCorePlugin.getDefault().getStateLocation().append("reports").toFile();
        try
        {
            // give eclipse a second to let go of files it maybe scanning
            Thread.sleep(1000);
            FileUtils.deleteDirectory(reportsDir);
        }
        catch (Exception e)
        {
            // sometimes eclipse is still holding onto files, wait a second then try again
            Thread.sleep(1000);
            FileUtils.deleteDirectory(reportsDir);
        }
    }

    @Test
    public void testGetReportLocation_ReportNotGenerated() throws CoreException
    {
        TestProjectProvider provider = new TestProjectProvider(
                    WindupCoreTestPlugin.PLUGIN_ID, null, "Portal-WAR", false);
        IProject project = provider.getProject();

        IFile jspFile = project.getFile(new Path("WebContent/WebContent/Portal.jsp"));
        String reportLocation = windupService.getReportLocation(jspFile);

        Assert.assertNull("Report location should be null for a resource in a "
                    + "project who's Windup report has not been generated", reportLocation);
    }

    @Test
    public void testGetReportLocation_ReportGenerated_ResourceDoesNotHaveReportResource() throws CoreException
    {
        TestProjectProvider provider = new TestProjectProvider(
                    WindupCoreTestPlugin.PLUGIN_ID, null, "Portal-WAR", false);
        IProject project = provider.getProject();

        IFile folder = project.getFile(new Path("WebContent/WebContent"));
        String reportLocation = windupService.getReportLocation(folder);

        Assert.assertNull("Report location should be null for a resource that "
                    + "does not have a corresponding Windup report resource", reportLocation);
    }

    @Ignore
    @Test
    public void testGenerateReport() throws CoreException
    {
        TestProjectProvider provider = new TestProjectProvider(
                    WindupCoreTestPlugin.PLUGIN_ID, null, "WAS-EAR", false);
        IProject project = provider.getProject();

        //windupService.generateGraph(project);

        // test that the report home file exists
        String reportHomeLocation = windupService.getReportLocation(project);
        Assert.assertTrue("The index.html for the generated report should exist.", new File(reportHomeLocation).exists());

        // test that a report file exists for JSP file
        IFile xmlFile = project.getFile(new Path("EarContent/META-INF/deployment.xml"));
        String xmlReportLocation = windupService.getReportLocation(xmlFile);
        Assert.assertNotNull("JSP Report Location should be found", xmlReportLocation);
        File xmlReportFile = new File(xmlReportLocation);
        Assert.assertTrue("A report resource should exist for " + xmlFile, xmlReportFile.exists());
    }

    @Ignore
    @Test
    public void testGenerateReports() throws CoreException
    {
        // import test projects
        TestProjectProvider portalProjectProvider = new TestProjectProvider(
                    WindupCoreTestPlugin.PLUGIN_ID, null, "Portal-WAR", false);

        TestProjectProvider wasProjectProvider = new TestProjectProvider(
                    WindupCoreTestPlugin.PLUGIN_ID, null, "WAS-EAR", false);

        IProject portalProject = portalProjectProvider.getProject();
        IProject wasProject = wasProjectProvider.getProject();

        // generate reports
        IProject[] projects = new IProject[] { portalProject, wasProject };
        //windupService.generateGraph(projects, null);

        // verify report index exists for all projects that reports were generated for
        for (IProject project : projects)
        {
            String reportHomeLocation = windupService.getReportLocation(project);
            Assert.assertTrue("The index.html for the generated report should exist.", new File(reportHomeLocation).exists());
        }

        // test that a report file exists for WAS deployment file in the was project
        IFile deploymentFile = wasProject.getFile(new Path("EarContent/META-INF/deployment.xml"));
        String deploymentReportLocation = windupService.getReportLocation(deploymentFile);
        File deploymentReportFile = new File(deploymentReportLocation);
        Assert.assertTrue("A report resource should exist for " + deploymentReportFile, deploymentReportFile.exists());
    }
    
    @Ignore
    @Test
    public void testReportExists() throws CoreException
    {
        TestProjectProvider provider = new TestProjectProvider(
                    WindupCoreTestPlugin.PLUGIN_ID, null, "Portal-WAR", false);
        IProject project = provider.getProject();

        //windupService.generateGraph(project);

        boolean reportExists = windupService.getReportLocation(project) != null;
        Assert.assertTrue("WindupService should report that the windup report exists for the given project.", reportExists);
    }

    @Ignore
    @Test
    public void testAddWindupReportListener() throws CoreException
    {
        TestProjectProvider provider = new TestProjectProvider(
                    WindupCoreTestPlugin.PLUGIN_ID, null, "Portal-WAR", false);
        final IProject project = provider.getProject();

        final List<IProject> notifiedProjects = new ArrayList<IProject>();

        windupService.addWindupListener(new IWindupListener()
        {
            @Override
            public void graphGenerated(IProject reportGeneratedForProject)
            {
                notifiedProjects.add(reportGeneratedForProject);
            }
        });

        //windupService.generateGraph(project);

        Assert.assertTrue("Listener was not notified of report generation for the project.",
                    notifiedProjects.contains(project));
    }

    @Ignore
    @Test
    public void testRemoveWindupReportListener() throws CoreException
    {
        TestProjectProvider provider = new TestProjectProvider(
                    WindupCoreTestPlugin.PLUGIN_ID, null, "Portal-WAR", false);
        final IProject project = provider.getProject();

        final List<IProject> notifiedProjects = new ArrayList<IProject>();

        IWindupListener listener = new IWindupListener()
        {
            @Override
            public void graphGenerated(IProject reportGeneratedForProject)
            {
                notifiedProjects.add(reportGeneratedForProject);
            }
        };

        windupService.addWindupListener(listener);
        windupService.removeWindupListener(listener);

        //windupService.generateGraph(project);

        Assert.assertTrue("Listener should not have been notified of report generation.",
                    notifiedProjects.isEmpty());
    }
}
