/*-
 * Copyright (c) 2012 Red Hat, Inc.
 *
 * Licensed 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.fedoraproject.maven.rpminstall.plugin;

import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.math.BigDecimal;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.apache.maven.artifact.Artifact;
import org.fedoraproject.maven.Configuration;

public class Package
    implements Comparable<Package>
{
    private final String suffix;

    private boolean pureDevelPackage = true;

    public Package( String name )
    {
        suffix = name.equals( "" ) ? "" : "-" + name;
    }

    private final FragmentFile depmap = new FragmentFile();

    class TargetFile
    {
        File sourceFile;

        String dirPath;

        String targetName;
    }

    private final List<TargetFile> targetFiles = new LinkedList<>();

    public void addFile( File file, String dirPath, String fileName )
    {
        TargetFile target = new TargetFile();
        target.sourceFile = file;
        target.dirPath = dirPath;
        target.targetName = fileName;
        targetFiles.add( target );
    }

    public void addPomFile( File file, Artifact artifact )
    {
        String jppGroupId = "JPP/" + Configuration.getInstallName();
        String jppArtifactId = artifact.getArtifactId();
        String pomName = jppGroupId.replace( '/', '.' ) + "-" + jppArtifactId + ".pom";
        addFile( file, Configuration.getInstallPomDir(), pomName );

        addDepmap( artifact );
    }

    private static boolean containsNativeCode( File jar )
    {
        // TODO: implement
        return false;
    }

    public void addJarFile( File file, Artifact artifact, BigDecimal javaVersion )
    {
        pureDevelPackage = false;

        String jarDir =
            containsNativeCode( file ) ? Configuration.getInstallJniDir() : Configuration.getInstallJarDir();
        addFile( file, jarDir + "/" + Configuration.getInstallName(), artifact.getArtifactId() + ".jar" );

        depmap.addJavaVersionRequirement( javaVersion );
    }

    private void installFiles( Installer installer )
        throws IOException
    {
        for ( TargetFile target : targetFiles )
        {
            installer.installFile( target.sourceFile, target.dirPath, target.targetName );
        }
    }

    public void addDepmap( Artifact artifact )
    {
        String groupId = artifact.getGroupId();
        String artifactId = artifact.getArtifactId();
        String version = artifact.getVersion();

        depmap.addMapping( groupId, artifactId, version, "JPP/" + Configuration.getInstallName(), artifactId );
    }

    public void addRequires( String groupId, String artifactId )
    {
        depmap.addDependency( groupId, artifactId );
    }

    public void addDevelRequires( String groupId, String artifactId )
    {
        depmap.addDevelDependency( groupId, artifactId );
    }

    private void installMetadata( Installer installer )
        throws IOException
    {
        depmap.optimize();

        if ( !depmap.isEmpty() )
        {
            File file = File.createTempFile( "xmvn", ".xml" );
            depmap.write( file, pureDevelPackage );
            String depmapName = Configuration.getInstallName() + suffix + ".xml";
            addFile( file, Configuration.getInstallDepmapDir(), depmapName );
        }
    }

    private void createFileList()
        throws IOException
    {
        Set<String> targetNames = new TreeSet<>();
        for ( TargetFile target : targetFiles )
        {
            File file = new File( target.dirPath, target.targetName );
            targetNames.add( file.getPath() );
        }

        PrintStream ps = new PrintStream( ".mfiles" + suffix );
        for ( String path : targetNames )
        {
            ps.println( "/" + path );
        }
        ps.close();
    }

    public void install( Installer installer )
        throws IOException
    {
        installMetadata( installer );
        installFiles( installer );
        createFileList();
    }

    @Override
    public int compareTo( Package rhs )
    {
        return suffix.compareTo( rhs.suffix );
    }
}

@@ -942,16 +942,101 @@
 uration;
+%0Aimport org.fedoraproject.maven.Rule;%0Aimport org.fedoraproject.maven.utils.FileUtils;
 %0A%0Apublic
@@ -1773,32 +1773,214 @@
 arget );%0A    %7D%0A%0A
+    public void addFile( File file, String target )%0A    %7B%0A        File targetFile = new File( target );%0A        addFile( file, targetFile.getParent(), targetFile.getName() );%0A    %7D%0A%0A
     public void 
@@ -2552,16 +2552,43 @@
 rsion )%0A
+        throws IOException%0A
     %7B%0A  
@@ -2632,240 +2632,1008 @@
     
-String jarDir =%0A            containsNativeCode( file ) ? Configuration.getInstallJniDir() : Configuration.getInstallJarDir();%0A        addFile( file, jarDir + %22/%22 + Configuration.getInstallName(), artifact.getArtifactId() + %22.jar%22 );
+List%3CString%3E extraList = new LinkedList%3C%3E();%0A        for ( Rule rule : Configuration.getInstallFiles() )%0A            if ( rule.getPattern().matches( artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion() ) )%0A                extraList.add( rule.getReplacementString() );%0A        // TODO: Allow use of @1,@2,... in file name%0A%0A        String baseFile = Configuration.getInstallName() + %22/%22 + artifact.getArtifactId();%0A        if ( !extraList.isEmpty() )%0A            baseFile = extraList.remove( 0 );%0A%0A        String jarDir =%0A            containsNativeCode( file ) ? Configuration.getInstallJniDir() : Configuration.getInstallJarDir();%0A        addFile( file, jarDir + %22/%22 + baseFile );%0A%0A        for ( String symlink : extraList )%0A        %7B%0A            File symlinkFile = FileUtils.createAnonymousSymlink( %22/%22 + jarDir + %22/%22 + baseFile );%0A            if ( !symlink.startsWith( %22/%22 ) )%0A                symlink = jarDir + %22/%22 + symlink;%0A            addFile( symlinkFile, symlink );%0A        %7D
 %0A%0A  

Add support for creating symlinks to jars