package org.apache.maven.shared.release.util;

/*
 * 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.
 */

import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.maven.model.Model;
import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.release.ReleaseExecutionException;
import org.apache.maven.shared.release.config.ReleaseDescriptor;
import org.apache.maven.shared.release.config.ReleaseDescriptorBuilder;
import org.apache.maven.shared.release.config.ReleaseUtils;
import org.codehaus.plexus.interpolation.InterpolationException;
import org.codehaus.plexus.interpolation.MapBasedValueSource;
import org.codehaus.plexus.interpolation.ObjectBasedValueSource;
import org.codehaus.plexus.interpolation.PrefixAwareRecursionInterceptor;
import org.codehaus.plexus.interpolation.PrefixedObjectValueSource;
import org.codehaus.plexus.interpolation.StringSearchInterpolator;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.ReaderFactory;

/**
 * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
 * @version $Id$
 */
public class ReleaseUtil
{
    @SuppressWarnings( "checkstyle:constantname" )
    public static final String RELEASE_POMv4 = "release-pom.xml";

    @SuppressWarnings( "checkstyle:constantname" )
    public static final String POMv4 = "pom.xml";

    private static final String FS = File.separator;

    /**
     * The line separator to use.
     */
    public static final String LS = System.getProperty( "line.separator" );

    private ReleaseUtil()
    {
        // noop
    }

    public static MavenProject getRootProject( List<MavenProject> reactorProjects )
    {
        MavenProject project = reactorProjects.get( 0 );
        for ( MavenProject currentProject : reactorProjects )
        {
            if ( currentProject.isExecutionRoot() )
            {
                project = currentProject;
                break;
            }
        }

        return project;
    }

    public static File getStandardPom( MavenProject project )
    {
        if ( project == null )
        {
            return null;
        }

        File pom = project.getFile();

        if ( pom == null )
        {
            return null;
        }

        File releasePom = getReleasePom( project );
        if ( pom.equals( releasePom ) )
        {
            pom = new File( pom.getParent(), POMv4 );
        }

        return pom;
    }

    public static File getReleasePom( MavenProject project )
    {
        if ( project == null )
        {
            return null;
        }

        File pom = project.getFile();

        if ( pom == null )
        {
            return null;
        }

        return new File( pom.getParent(), RELEASE_POMv4 );
    }

    /**
     * Gets the string contents of the specified XML file. Note: In contrast to an XML processor, the line separators in
     * the returned string will be normalized to use the platform's native line separator. This is basically to save
     * another normalization step when writing the string contents back to an XML file.
     *
     * @param file The path to the XML file to read in, must not be <code>null</code>.
     * @return The string contents of the XML file.
     * @throws IOException If the file could not be opened/read.
     */
    public static String readXmlFile( File file )
        throws IOException
    {
        return readXmlFile( file, LS );
    }

    public static String readXmlFile( File file, String ls )
        throws IOException
    {
        try ( Reader reader = ReaderFactory.newXmlReader( file ) )
        {
            return normalizeLineEndings( IOUtil.toString( reader ), ls );
        }
    }

    /**
     * Normalizes the line separators in the specified string.
     *
     * @param text The string to normalize, may be <code>null</code>.
     * @param separator The line separator to use for normalization, typically "\n" or "\r\n", must not be
     *            <code>null</code>.
     * @return The input string with normalized line separators or <code>null</code> if the string was <code>null</code>
     *         .
     */
    public static String normalizeLineEndings( String text, String separator )
    {
        String norm = text;
        if ( text != null )
        {
            norm = text.replaceAll( "(\r\n)|(\n)|(\r)", separator );
        }
        return norm;
    }

    public static ReleaseDescriptor createBasedirAlignedReleaseDescriptor( ReleaseDescriptor releaseDescriptor,
                                                                           List<MavenProject> reactorProjects )
        throws ReleaseExecutionException
    {
        String basedir;
        try
        {
            basedir = getCommonBasedir( reactorProjects );
        }
        catch ( IOException e )
        {
            throw new ReleaseExecutionException( "Exception occurred while calculating common basedir: "
                + e.getMessage(), e );
        }

        int parentLevels =
            getBaseWorkingDirectoryParentCount( basedir,
                                                FileUtils.normalize( releaseDescriptor.getWorkingDirectory() ) );

        String url = releaseDescriptor.getScmSourceUrl();
        url = realignScmUrl( parentLevels, url );

        ReleaseDescriptorBuilder builder = new ReleaseDescriptorBuilder();
        builder.setWorkingDirectory( basedir );
        builder.setScmSourceUrl( url );
        return ReleaseUtils.buildReleaseDescriptor( builder );
    }

    public static String getCommonBasedir( List<MavenProject> reactorProjects )
        throws IOException
    {
        return getCommonBasedir( reactorProjects, FS );
    }

    public static String getCommonBasedir( List<MavenProject> reactorProjects, String separator )
        throws IOException
    {
        String[] baseDirs = new String[reactorProjects.size()];
        int idx = 0;
        for ( MavenProject p : reactorProjects )
        {
            String dir = p.getBasedir().getCanonicalPath();

            // always end with separator so that we know what is a path and what is a partial directory name in the
            // next call
            if ( !dir.endsWith( separator ) )
            {
                dir = dir + separator;
            }
            baseDirs[idx++] = dir;
        }

        String basedir = StringUtils.getCommonPrefix( baseDirs );

        int separatorPos = basedir.lastIndexOf( separator );
        if ( !basedir.endsWith( separator ) && separatorPos >= 0 )
        {
            basedir = basedir.substring( 0, separatorPos );
        }

        if ( basedir.endsWith( separator ) && basedir.length() > 1 )
        {
            basedir = basedir.substring( 0, basedir.length() - 1 );
        }

        return basedir;
    }

    public static int getBaseWorkingDirectoryParentCount( String basedir, String workingDirectory )
    {
        int num = 0;

        // we can safely assume case-insensitivity as we are just backtracking, not comparing. This helps with issues
        // on Windows with C: vs c:
        workingDirectory = FilenameUtils.normalize( workingDirectory.toLowerCase( Locale.ENGLISH ) );
        basedir = FilenameUtils.normalize( basedir.toLowerCase( Locale.ENGLISH ) );

        // MRELEASE-663
        // For Windows is does matter if basedir ends with a file-separator or not to be able to compare.
        // Using the parent of a dummy file makes it possible to compare them OS-independent
        Path workingDirectoryFile = Paths.get( workingDirectory, ".tmp" ).getParent();
        Path basedirFile = Paths.get( basedir, ".tmp" ).getParent();

        if ( !workingDirectoryFile.equals( basedirFile ) && workingDirectory.startsWith( basedir ) )
        {
            do
            {
                workingDirectoryFile = workingDirectoryFile.getParent();
                num++;
            }
            while ( !workingDirectoryFile.equals( basedirFile ) );
        }
        return num;
    }

    public static String realignScmUrl( int parentLevels, String url )
    {
        if ( !StringUtils.isEmpty( url ) )
        {
            // normalize
            url = url.replaceAll( "/\\./", "/" ).replaceAll( "/\\.$", "" ).
                            replaceAll( "/[^/]+/\\.\\./", "/" ).replaceAll( "/[^/]+/\\.\\.$", "" );

            int index = url.length();
            String suffix = "";
            if ( url.endsWith( "/" ) )
            {
                index--;
                suffix = "/";
            }

            for ( int i = 0; i < parentLevels && index > 0; i++ )
            {
                index = url.lastIndexOf( '/', index - 1 );
            }

            if ( index > 0 )
            {
                url = url.substring( 0, index ) + suffix;
            }

        }
        return url;
    }

    public static boolean isSymlink( File file )
        throws IOException
    {
        return !file.getAbsolutePath().equals( file.getCanonicalPath() );
    }

    public static String interpolate( String value, Model model )
        throws ReleaseExecutionException
    {
        if ( value != null && value.contains( "${" ) )
        {
            StringSearchInterpolator interpolator = new StringSearchInterpolator();
            List<String> pomPrefixes = Arrays.asList( "pom.", "project." );
            interpolator.addValueSource( new PrefixedObjectValueSource( pomPrefixes, model, false ) );
            interpolator.addValueSource( new MapBasedValueSource( model.getProperties() ) );
            interpolator.addValueSource( new ObjectBasedValueSource( model ) );
            try
            {
                value = interpolator.interpolate( value, new PrefixAwareRecursionInterceptor( pomPrefixes ) );
            }
            catch ( InterpolationException e )
            {
                throw new ReleaseExecutionException(
                                                     "Failed to interpolate " + value + " for project " + model.getId(),
                                                     e );
            }
        }
        return value;
    }
}
