/*
 * 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.msbuild.xdt;

import com.google.common.base.Preconditions;
import com.google.common.io.ByteStreams;
import com.google.common.io.Files;
import com.google.common.io.InputSupplier;
import com.google.common.io.OutputSupplier;
import com.google.common.io.Resources;
import npanday.PlatformUnsupportedException;
import npanday.msbuild.MsbuildException;
import npanday.msbuild.MsbuildInvocationParameters;
import npanday.msbuild.MsbuildInvoker;
import npanday.vendor.VendorRequirement;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

/**
 * @author <a href="mailto:lcorneliussen@apache.org">Lars Corneliussen</a>
 * @plexus.component role="npanday.msbuild.xdt.XmlDocumentTransformer"
 */
public class XmlDocumentTransformer
{
    /**
     * @plexus.requirement
     */
    private MsbuildInvoker msbuild;

    private File workingFolder;

    /**
     * There will be some need for temporary files; these will be stored in this folder.
     *
     * @param workingFolder
     */
    public void setWorkingFolder( File workingFolder )
    {
        this.workingFolder = workingFolder;
    }

    public void transform(
        VendorRequirement vendorRequirement, File baseFile, File transformationFile, File targetFile ) throws
        PlatformUnsupportedException, XmlDocumentTransformException
    {
        Preconditions.checkArgument( baseFile != null, "Argument 'baseFile' was null!" );
        Preconditions.checkArgument( transformationFile != null, "Argument 'baseFile' was null!" );
        Preconditions.checkArgument( targetFile != null, "Argument 'baseFile' was null!" );

        Preconditions.checkNotNull( workingFolder, "tempFolder was not yet specified!" );

        final String resourceName = "/msbuild/xdt.msbuild.xml";
        final File buildFile;
        try
        {
            buildFile = extractResource( resourceName );
        }
        catch ( IOException e )
        {
            throw new XmlDocumentTransformException(
                "NPANDAY-136-001: Error when extracting build file from resources: " + resourceName, e
            );
        }

        final MsbuildInvocationParameters parameters = new MsbuildInvocationParameters(
            vendorRequirement, buildFile
        );

        parameters.setProperty( "Source", baseFile.getAbsolutePath() );
        parameters.setProperty( "Transform", transformationFile.getAbsolutePath() );
        parameters.setProperty( "Destination", targetFile.getAbsolutePath() );

        targetFile.getParentFile().mkdirs();

        try
        {
            msbuild.invoke( parameters );
        }
        catch ( MsbuildException e )
        {
            throw new XmlDocumentTransformException(
                "NPANDAY-136-000: Error occured while trying to transform '" + baseFile.getName() + "' with "
                    + transformationFile.getName(), e
            );
        }
    }

    private File extractResource( String resourceName ) throws IOException
    {
        final URL resource = Resources.getResource( getClass(), resourceName );
        final InputSupplier<InputStream> in = Resources.newInputStreamSupplier(
            resource
        );

        final File outFile = new File( new File( workingFolder, "tmp" ), resourceName );
        outFile.getParentFile().mkdirs();
        outFile.createNewFile();
        final OutputSupplier<FileOutputStream> out = Files.newOutputStreamSupplier(
            outFile
        );

        ByteStreams.copy( in, out );

        return outFile;
    }
}

@@ -1296,16 +1296,64 @@
 irement;
+%0Aimport org.codehaus.plexus.interpolation.os.Os;
 %0A%0Aimport
@@ -3403,16 +3403,98 @@
 ath() );
+%0A        parameters.setProperty( %22VisualStudioVersion%22, findRequiredVSVersion() );
 %0A%0A      
@@ -3899,24 +3899,1068 @@
    %7D%0A    %7D%0A%0A
+    private static String findRequiredVSVersion() throws XmlDocumentTransformException %7B%0A        if (Os.isArch(%22amd64%22)) %7B%0A            return findRequiredVSVersion(System.getenv(%22PROGRAMFILES(X86)%22));%0A        %7D%0A        else %7B%0A            return findRequiredVSVersion(System.getenv(%22PROGRAMFILES%22));%0A        %7D%0A    %7D%0A%0A    private static String findRequiredVSVersion(String programfiles) throws XmlDocumentTransformException %7B%0A        File%5B%5D dirs = new File( programfiles, %22MSBuild/Microsoft/VisualStudio%22 ).listFiles();%0A        String version = null;%0A        if (dirs != null) %7B%0A            for (File dir : dirs) %7B%0A                if (new File(dir, %22Web/Microsoft.Web.Publishing.Tasks.dll%22).exists()) %7B%0A                    version = dir.getName().substring(1);%0A                %7D%0A            %7D%0A        %7D%0A        if (version == null) %7B%0A            throw new XmlDocumentTransformException(%22Unable to find required tasks file in '%22 + programfiles +%0A                    %22%5C%5CMSBuild%5C%5CMicrosoft%5C%5CVisualStudio'%22);%0A        %7D%0A        return version;%0A    %7D%0A%0A
     private 

handle mismatched msbuild versions with the installed Visual Studio tools