/*
 *  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.myfaces.buildtools.maven2.plugin.javascript.jmt;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.NumberFormat;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
import org.apache.maven.artifact.resolver.ArtifactResolver;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.apache.myfaces.buildtools.maven2.plugin.javascript.jmt.compress.CompressionException;
import org.apache.myfaces.buildtools.maven2.plugin.javascript.jmt.compress.IsolatedClassLoader;
import org.apache.myfaces.buildtools.maven2.plugin.javascript.jmt.compress.JSCompressor;
import org.apache.myfaces.buildtools.maven2.plugin.javascript.jmt.compress.JSCompressorProxy;
import org.apache.myfaces.buildtools.maven2.plugin.javascript.jmt.compress.JSMinCompressor;
import org.codehaus.plexus.util.DirectoryScanner;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.IOUtil;

/**
 * Abstact mojo for compressing JavaScripts.
 * 
 * @author <a href="mailto:nicolas@apache.org">nicolas De Loof</a>
 */
public abstract class AbstractCompressMojo
    extends AbstractMojo
{

    /**
     * Resolves the artifacts and dependencies.
     * 
     * @component
     */
    private ArtifactResolver artifactResolver;

    /**
     * Create Artifact references
     * 
     * @component
     */
    private ArtifactFactory artifactFactory;

    /**
     * The local repository
     * 
     * @parameter expression="${localRepository}"
     * @required
     */
    private ArtifactRepository localRepository;

    /**
     * For retrieval of artifact's metadata.
     * 
     * @component
     */
    private ArtifactMetadataSource metadataSource;

    /**
     * The remote repositories declared in the pom.
     * 
     * @parameter expression="${project.pluginArtifactRepositories}"
     */
    private List remoteRepositories;

    /**
     *
     */
    private static final NumberFormat INTEGER = NumberFormat.getIntegerInstance();

    private static final String HR = StringUtils.rightPad( "", 78, "-" );

    /**
     * The maven project we are working on.
     * 
     * @parameter default-value="${project}"
     * @required
     * @readonly
     */
    MavenProject project;

    /**
     * The available compressors
     */
    private Map compressors = new HashMap();
    {
        compressors.put( "jsmin", new JSMinCompressor() );
    }

    /**
     * Optimization level, from 0 to 9
     * 
     * @parameter default-value="9"
     */
    private int optimizationLevel;

    /**
     * JS Language version (130 for JS 1.3)
     * 
     * @parameter default-value="130"
     */
    private int languageVersion;

    /**
     * The compressor to used. Either "shrinksafe", "yahooui" or "jsmin" for default compressor, 
     * or a custom one provided as an artifact in repo org.codehaus.mojo.javascript:<xxx>-compressor.
     * 
     * @parameter default-value="jsmin"
     */
    private String compressor;

    /**
     * Don't display compression stats
     * 
     * @parameter
     */
    private boolean skipStats;

    private static final String[] DEFAULT_INCLUDES = new String[] { "**/*.js" };

    /**
     * Inclusion patterns
     * 
     * @parameter
     */
    private String[] includes;

    /**
     * Exclusion patterns
     * 
     * @parameter
     */
    private String[] excludes;

    /**
     * A special token to recognize lines to be removed from scripts (debugging
     * code).
     * 
     * @parameter
     */
    private String strip;

    /**
     * {@inheritDoc}
     * 
     * @see org.apache.maven.plugin.AbstractMojo#execute()
     */
    public void execute()
        throws MojoExecutionException
    {
        DirectoryScanner scanner = new DirectoryScanner();
        scanner.setBasedir( getSourceDirectory() );
        if ( includes == null )
        {
            includes = DEFAULT_INCLUDES;
        }
        scanner.setIncludes( includes );
        scanner.addDefaultExcludes();
        if ( excludes != null )
        {
            scanner.setExcludes( excludes );
        }
        scanner.scan();
        String[] files = scanner.getIncludedFiles();

        // if ( !Context.isValidOptimizationLevel( optimizationLevel ) )
        // {
        // throw new MojoExecutionException( "optimizationLevel is invalid" );
        // }
        // if ( !Context.isValidLanguageVersion( languageVersion ) )
        // {
        // throw new MojoExecutionException( "languageVersion is invalid" );
        // }

        JSCompressor jscompressor = getCompressor();

        logStats( HR );
        getOutputDirectory().mkdirs();
        long saved = 0;
        for ( int i = 0; i < files.length; i++ )
        {
            String file = files[i];
            saved = compress( jscompressor, file );
        }
        logStats( HR );
        logStats( "compression saved " + INTEGER.format( saved ) + " bytes" );
    }

    private File stripDebugs( File file )
        throws MojoExecutionException
    {
        if ( strip == null )
        {
            return file;
        }
        try
        {

            File stripped = File.createTempFile( "stripped", ".js" );

            BufferedReader reader = new BufferedReader( new FileReader( file ) );
            PrintWriter writer = new PrintWriter( stripped );
            String line;
            while ( ( line = reader.readLine() ) != null )
            {
                if ( !line.trim().startsWith( strip ) )
                {
                    writer.println( line );
                }
            }
            IOUtil.close( reader );
            IOUtil.close( writer );

            FileUtils.copyFile( stripped, file );
            stripped.delete();
        }
        catch ( IOException e )
        {
            throw new MojoExecutionException( "Failed to strip debug code in " + file, e );
        }
        return file;
    }

    private JSCompressor getCompressor()
        throws MojoExecutionException
    {
        if ( compressors.containsKey( compressor ) )
        {
            return (JSCompressor) compressors.get( compressor );
        }

        // Inspired by the surefire plugin
        // allows to use multiple compressor that rely on modifier Rhino engines
        // without dependencies/classpath conflicts

        //String id = compressor.toLowerCase() + "-compressor";
        /*
        String id = "myfaces-javascript-plugin";

        // TODO don't have version hardcoded
        Artifact compressorArtifact =
            artifactFactory.createDependencyArtifact( "org.apache.myfaces.buildtools", id,
                VersionRange.createFromVersion( "1.0.1-SNAPSHOT" ), "jar", null,
                Artifact.SCOPE_RUNTIME );

        Artifact originatingArtifact =
            artifactFactory.createBuildArtifact( "dummy", "dummy", "1.0", "jar" );

        ArtifactResolutionResult dependencies;
        try
        {
            dependencies =
                artifactResolver.resolveTransitively( Collections.singleton( compressorArtifact ),
                    originatingArtifact, localRepository, remoteRepositories, metadataSource, null );
        }
        catch ( Exception e )
        {
            getLog().info( "Failed to load compressor artifact " + compressorArtifact.toString() );
            throw new MojoExecutionException( "Failed to load compressor artifact"
                + compressorArtifact.toString(), e );
        }

        IsolatedClassLoader classLoader = new IsolatedClassLoader( dependencies.getArtifacts() );
        */
        compressor = StringUtils.capitalize( compressor );
        String compressorClassName =
            "org.apache.myfaces.buildtools.maven2.plugin.javascript.jmt.compress." + compressor + "Compressor";
        Class compressorClass;
        try
        {
            compressorClass = getClass().getClassLoader().loadClass( compressorClassName );
            //compressorClass = classLoader.loadClass( compressorClassName );
        }
        catch ( ClassNotFoundException e )
        {
            getLog().info( "Failed to load compressor class " + compressorClassName );
            throw new MojoExecutionException( "Failed to load compressor class"
                + compressorClassName, e );
        }

        JSCompressor jscompressor;
        try
        {
            jscompressor = new JSCompressorProxy( compressorClass.newInstance() );
        }
        catch ( Exception e )
        {
            getLog().info(
                "Failed to create a isolated-classloader proxy for " + compressorClassName );
            throw new MojoExecutionException( "Failed to create a isolated-classloader proxy for "
                + compressorClassName, e );
        }
        getLog().info( "Compressing javascript using " + compressor );

        compressors.put( compressor, jscompressor );
        return jscompressor;
    }

    private long compress( JSCompressor jscompressor, String file )
        throws MojoExecutionException
    {
        String name = file;
        if ( getExtension() != null )
        {
            int ext = file.lastIndexOf( '.' );
            name = file.substring( 0, ext ) + "-" + getExtension() + file.substring( ext );
        }
        File compressed = new File( getOutputDirectory(), name );
        compressed.getParentFile().mkdirs();
        File in = new File( getSourceDirectory(), file );
        if ( in.equals( compressed ) )
        {
            try
            {
                File temp = File.createTempFile( "compress", ".js" );
                long size = compress( in, temp, jscompressor );
                FileUtils.copyFile( temp, compressed );
                temp.delete();
                return size;
            }
            catch ( IOException e )
            {
                throw new MojoExecutionException( "Error creating temp file for compression", e );
            }
        }
        else
        {
            return compress( in, compressed, jscompressor );
        }
    }

    private long compress( File in, File compressed, JSCompressor jscompressor )
        throws MojoExecutionException
    {
        if ( in.length() > 0 )
        {
            File stripped = stripDebugs( in );
            try
            {
                jscompressor.compress( stripped, compressed, optimizationLevel, languageVersion );
            }
            catch ( CompressionException e )
            {
                throw new MojoExecutionException( "Failed to compress Javascript file "
                    + e.getScript(), e );
            }
            String describe = in.getName() + " (" + INTEGER.format( in.length() ) + " bytes) ";
            String title = StringUtils.rightPad( describe, 60, "." );
            logStats( title + " compressed at " + ratio( compressed, in ) + "%" );
            return in.length() - compressed.length();
        }
        else
        {
            try
            {
                compressed.createNewFile();
                getLog().info( in.getName() + " was zero length; not compressed." );
                return 0;
            }
            catch ( IOException e )
            {
                throw new MojoExecutionException( "Error handling zero length file.", e );
            }
        }
    }

    private long ratio( File compressed, File in )
    {
        long length = in.length();
        if ( length == 0 )
        {
            return 0;
        }
        return ( ( ( length - compressed.length() ) * 100 ) / length );
    }

    private void logStats( String line )
    {
        if ( skipStats )
        {
            return;
        }
        getLog().info( line );
    }

    /**
     * @return the extension to append to compressed scripts.
     */
    public abstract String getExtension();

    /**
     * @return the outputDirectory
     */
    protected abstract File getOutputDirectory();

    /**
     * @return the sourceDirectory
     */
    protected abstract File getSourceDirectory();

    protected void setLocalRepository( ArtifactRepository localRepository )
    {
        this.localRepository = localRepository;
    }
}
