/*
 * 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 npanday.plugin.azure;

import com.google.common.collect.Lists;
import npanday.ArtifactType;
import npanday.LocalRepositoryUtil;
import npanday.PathUtil;
import npanday.resolver.NPandayDependencyResolution;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.codehaus.plexus.util.IOUtil;

import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.List;
import java.util.Properties;
import java.util.Set;

/**
 * Packages roles specified in the dependencies into a common cloud service package (*.cspkg), accompanied
 * with a configuration template (*.cscfg).
 *
 * @author <a href="mailto:lcorneliussen@apache.org">Lars Corneliussen</a>
 * @goal create-package
 */
public class CreateCloudServicePackageMojo
    extends AbstractCSPackDeployMojo
{
    private File packageFile, templateConfigurationFile;

    /**
     * The service definition file that get passed along to cspack.
     *
     * @parameter expression="${azure.serviceDefinition}" default-value="${basedir}/ServiceDefinition.csdef"
     */
    private File serviceDefinitionFile;

    /**
     * If a vanilla cloud service configuration file should be generated and attached along with the package.
     *
     * @parameter expression="${azure.generateConfigurationFile}" default-value="true"
     */
    private boolean generateConfigurationFile;

    /**
     * @component
     */
    private NPandayDependencyResolution dependencyResolution;

    /**
     * The scope up to which dependencies should be included.
     *
     * @parameter default-value="runtime"
     */
    private String scope;

    /**
     * The location of the local Maven repository.
     *
     * @parameter expression="${settings.localRepository}"
     */
    private File localRepository;

    private void resolveDependencies() throws MojoExecutionException
    {
        try
        {
            dependencyResolution.require( project, LocalRepositoryUtil.create( localRepository ), scope );
        }
        catch ( ArtifactResolutionException e )
        {
            throw new MojoExecutionException(
                "NPANDAY-131-004: Could not satisfy required dependencies of scope " + scope, e
            );
        }
    }

    /**
     * Dependency aliases to use, in case they don't match the artifact ID.
     *
     * @parameter
     */
    private Properties aliases = new Properties();

    @Override
    protected void afterCommandExecution() throws MojoExecutionException
    {
        attachPackageFile();

        if ( generateConfigurationFile )
        {
            attachConfigurationFile();
        }
    }

    private void attachPackageFile() throws MojoExecutionException
    {
        if ( !packageFile.exists() )
        {
            throw new MojoExecutionException(
                "NPANDAY-123-001: CSPack seemed to fail on creating the package " + packageFile.getAbsolutePath()
            );
        }

        project.getArtifact().setFile( packageFile );
    }

    private void attachConfigurationFile() throws MojoExecutionException
    {
        if ( !templateConfigurationFile.exists() )
        {
            throw new MojoExecutionException(
                "NPANDAY-123-002: CSPack seemed to fail on creating the template configuration file "
                    + packageFile.getAbsolutePath()
            );

        }

        projectHelper.attachArtifact(
            project, ArtifactType.AZURE_CLOUD_SERVICE_CONFIGURATION.getPackagingType(), "generated",
            templateConfigurationFile
        );
    }

    @Override
    protected void beforeCommandExecution()
    {
        packageFile = new File(
            project.getBuild().getDirectory(),
            project.getArtifactId() + "." + ArtifactType.AZURE_CLOUD_SERVICE.getExtension()
        );

        templateConfigurationFile = new File(
            project.getBuild().getDirectory(), project.getArtifactId() + "-configtemplate" + "."
            + ArtifactType.AZURE_CLOUD_SERVICE_CONFIGURATION.getExtension()
        );
    }

    @Override
    protected List<String> getCommands() throws MojoExecutionException, MojoFailureException
    {
        List<String> commands = Lists.newArrayList();

        commands.add( serviceDefinitionFile.getAbsolutePath() );

        if ( generateConfigurationFile )
        {
            commands.add( "/generateConfigurationFile:" + templateConfigurationFile.getAbsolutePath() );
        }

        commands.add( "/out:" + packageFile.getAbsolutePath() );

        resolveDependencies();
        ScopeArtifactFilter filter = new ScopeArtifactFilter( scope );

        final Set projectDependencyArtifacts = project.getDependencyArtifacts();
        for ( Object artifactAsObject : projectDependencyArtifacts )
        {
            Artifact artifact = (Artifact) artifactAsObject;

            if (!filter.include( artifact ))
            {
                continue;
            }

            final boolean isWebRole = artifact.getType().equals(
                ArtifactType.MSDEPLOY_PACKAGE.getPackagingType()
            ) || artifact.getType().equals(
                ArtifactType.MSDEPLOY_PACKAGE.getExtension()
            );

            final boolean isWorkerRole = artifact.getType().equals(
                ArtifactType.DOTNET_APPLICATION.getPackagingType()
            ) || artifact.getType().equals(
                ArtifactType.DOTNET_APPLICATION.getExtension()
            );

            // if the artifact ID is a key, replace it, otherwise use the original
            String dependencyArtifactId = aliases.getProperty( artifact.getArtifactId(), artifact.getArtifactId() );

            if ( !isWebRole && !isWorkerRole )
            {
                throw new MojoExecutionException(
                    "NPANDAY-123-005: Artifact type " + artifact.getType() + " of artifact " + dependencyArtifactId
                        + " is not supported for azure cloud services.\n\nPlease use "
                        + ArtifactType.DOTNET_APPLICATION.getPackagingType() + " for worker roles, and "
                        + ArtifactType.MSDEPLOY_PACKAGE.getPackagingType() + " for web roles"
                );
            }

            final File roleRoot = new File(
                PathUtil.getPreparedPackageFolder( project ), artifact.getArtifactId()
            );

            if ( isWebRole )
            {
                getLog().debug( "NPANDAY-123-003: Found web role " + dependencyArtifactId );
            }
            else if ( isWorkerRole )
            {
                getLog().debug( "NPANDAY-123-004: Found worker role " + dependencyArtifactId );
            }

            if ( !roleRoot.exists() )
            {
                throw new MojoExecutionException(
                    "NPANDAY-123-006: Could not find worker/web role root for " + dependencyArtifactId + ": "
                        + roleRoot
                );
            }

            File entryPoint = null; 
            if ( isWebRole )
            {
                String name = "bin" + File.separator + dependencyArtifactId + ".dll";
                entryPoint = new File( roleRoot, name );
                if ( entryPoint.exists() )
                {
                    commands.add(
                        "/role:" + dependencyArtifactId + ";" + roleRoot.getAbsolutePath() + ";" + entryPoint.getName()
                    );
                }
                else
                {
                    getLog().warn( "NPANDAY-123-005: entry point '" + entryPoint + "' could not be found" );
                    commands.add(
                        "/role:" + dependencyArtifactId + ";" + roleRoot.getAbsolutePath()
                    );
                }

                // TODO: 'Web/' is hardcoded here; where to get it from?
                commands.add(
                    "/sitePhysicalDirectories:" + dependencyArtifactId + ";Web;" + canonical( roleRoot )
                );
            }
            else if ( isWorkerRole )
            {
                entryPoint = new File( roleRoot, dependencyArtifactId + ".dll" );
                if ( !entryPoint.exists() )
                {
                    throw new MojoExecutionException(
                        "NPANDAY-123-007: Could not find entry point dll for " + dependencyArtifactId + ": "
                            + entryPoint
                    );
                }

                commands.add(
                    "/role:" + dependencyArtifactId + ";" + roleRoot.getAbsolutePath() + ";"
                        + entryPoint.getName()
                );
            }

            // TODO: enable configuration of different framework pr. role; default to frameworkVersion
            Properties properties = new Properties();
            String v = frameworkVersion != null ? "v" + frameworkVersion : "v4.0";
            properties.setProperty( "TargetFrameworkVersion", v );
            if ( entryPoint != null && entryPoint.exists() )
            {
                properties.setProperty( "EntryPoint", entryPoint.getName() );
            }

            File rolePropertiesFile = new File(project.getBuild().getDirectory(), dependencyArtifactId + ".roleproperties");
            PrintWriter writer = null;
            try
            {
                writer = new PrintWriter( new FileWriter( rolePropertiesFile ) );
                // can't use properties.store(), it writes a comment that CSPACK doesn't understand
                for ( String property : properties.stringPropertyNames() )
                {
                    writer.println( property + "=" + properties.getProperty( property ) );
                }

                commands.add(
                    "/rolePropertiesFile:" + dependencyArtifactId + ";" + rolePropertiesFile.getAbsolutePath()
                );
            }
            catch ( java.io.IOException e )
            {
                throw new MojoFailureException(
                    "NPANDAY-123-008: Error while creating role properties file for " + dependencyArtifactId, e );
            }
            finally
            {
                IOUtil.close( writer );
            }
        }

        return commands;
    }

    private String canonical( File f )
    {
        String path = f.getAbsolutePath();

        // CSPack is very fussy - lowercase the drive letter and you get
        // sitesroot, uppercase and it is omitted (!)
        // See: http://social.msdn.microsoft.com/Forums/bs-Latn-BA/windowsazuredevelopment/thread/014ce124-5ca6-46ce-b1ea-3d677a092f65
        return path.substring( 0, 1 ).toLowerCase() + path.substring( 1 );
    }
}
