package org.apache.maven.artifact.repository.metadata;

/*
 * 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 static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;

import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

class MetadataTest
{

    Artifact artifact;

    Metadata target;

    @BeforeEach
    void before()
    {
        artifact = new DefaultArtifact( "myGroup:myArtifact:1.0-SNAPSHOT" );
        target = createMetadataFromArtifact( artifact );
    }

    /*--- START test common metadata ---*/
    @Test
    void mergeEmptyMetadata()
        throws Exception
    {
        Metadata metadata = new Metadata();
        assertFalse( metadata.merge( new Metadata() ) );
    }

    @Test
    void mergeDifferentGAV()
        throws Exception
    {
        // merge implicitly assumes that merge is only called on the same GAV and does not perform any validation here!
        Metadata source = new Metadata();
        source.setArtifactId( "source-artifact" );
        source.setGroupId( "source-group" );
        source.setVersion( "2.0" );
        assertFalse( target.merge( source ) );
        assertEquals( "myArtifact", target.getArtifactId() );
        assertEquals( "myGroup", target.getGroupId() );
        assertEquals( "1.0-SNAPSHOT", target.getVersion() );
    }
    /*--- END test common metadata ---*/

    /*--- START test "groupId/artifactId/version" metadata ---*/
    @Test
    void mergeSnapshotWithEmptyList()
        throws Exception
    {
        Snapshot snapshot = new Snapshot();
        snapshot.setBuildNumber( 3 );
        snapshot.setTimestamp( "20200710.072412" );
        target.getVersioning().setSnapshot( snapshot );
        target.getVersioning().setLastUpdated( "20200921071745" );
        SnapshotVersion sv = new SnapshotVersion();
        sv.setClassifier( "sources" );
        sv.setExtension( "jar" );
        sv.setUpdated( "20200710072412" );
        target.getVersioning().addSnapshotVersion( sv );

        Metadata source = createMetadataFromArtifact( artifact );
        // nothing should be actually changed, but still merge returns true
        assertTrue( target.merge( source ) );

        // NOTE! Merge updates last updated to source
        assertEquals( "20200921071745", source.getVersioning().getLastUpdated() );

        assertEquals( "myArtifact", target.getArtifactId() );
        assertEquals( "myGroup", target.getGroupId() );

        assertEquals( 3, target.getVersioning().getSnapshot().getBuildNumber() );
        assertEquals( "20200710.072412", target.getVersioning().getSnapshot().getTimestamp() );

        assertEquals( 1, target.getVersioning().getSnapshotVersions().size() );
        assertEquals( "sources", target.getVersioning().getSnapshotVersions().get( 0 ).getClassifier() );
        assertEquals( "jar", target.getVersioning().getSnapshotVersions().get( 0 ).getExtension() );
        assertEquals( "20200710072412", target.getVersioning().getSnapshotVersions().get( 0 ).getUpdated() );
    }

    @Test
    void mergeWithSameSnapshotWithDifferentVersionsAndNewerLastUpdated()
    {
        Metadata source = createMetadataFromArtifact( artifact );
        Date before = new Date( System.currentTimeMillis() - 5000 );
        Date after = new Date( System.currentTimeMillis() );
        addSnapshotVersion( target.getVersioning(), "jar", before, "1", 1 );
        SnapshotVersion sv2 =
            addSnapshotVersion( source.getVersioning(), "jar", after, "1.0-" + formatDate( after, true ) + "-2", 2 );
        SnapshotVersion sv3 =
            addSnapshotVersion( source.getVersioning(), "pom", after, "1.0-" + formatDate( after, true ) + "-2", 2 );
        assertTrue( target.merge( source ) );
        Versioning actualVersioning = target.getVersioning();
        assertEquals( 2, actualVersioning.getSnapshotVersions().size() );
        assertEquals( sv2, actualVersioning.getSnapshotVersions().get( 0 ) );
        assertEquals( sv3, actualVersioning.getSnapshotVersions().get( 1 ) );
        assertEquals( formatDate( after, false ), actualVersioning.getLastUpdated() );
        assertEquals( formatDate( after, true ), actualVersioning.getSnapshot().getTimestamp() );
        assertEquals( 2, actualVersioning.getSnapshot().getBuildNumber() );
    }

    @Test
    void mergeWithSameSnapshotWithDifferentVersionsAndOlderLastUpdated()
    {
        Metadata source = createMetadataFromArtifact( artifact );
        Date before = new Date( System.currentTimeMillis() - 5000 );
        Date after = new Date( System.currentTimeMillis() );
        SnapshotVersion sv1 = addSnapshotVersion( target.getVersioning(), after, artifact );
        addSnapshotVersion( source.getVersioning(), before, artifact );
        // nothing should be updated, as the target was already updated at a later date than source
        assertFalse( target.merge( source ) );
        assertEquals( 1, target.getVersioning().getSnapshotVersions().size() );
        assertEquals( sv1, target.getVersioning().getSnapshotVersions().get( 0 ) );
        assertEquals( formatDate( after, false ), target.getVersioning().getLastUpdated() );
        assertEquals( formatDate( after, true ), target.getVersioning().getSnapshot().getTimestamp() );
    }

    @Test
    void mergeWithSameSnapshotWithSameVersionAndTimestamp()
    {
        Metadata source = createMetadataFromArtifact( artifact );
        Date date = new Date();
        addSnapshotVersion( target.getVersioning(), date, artifact );
        SnapshotVersion sv1 = addSnapshotVersion( source.getVersioning(), date, artifact );
        // although nothing has changed merge returns true, as the last modified date is equal
        // TODO: improve merge here?
        assertTrue( target.merge( source ) );
        assertEquals( 1, target.getVersioning().getSnapshotVersions().size() );
        assertEquals( sv1, target.getVersioning().getSnapshotVersions().get( 0 ) );
        assertEquals( formatDate( date, false ), target.getVersioning().getLastUpdated() );
        assertEquals( formatDate( date, true ), target.getVersioning().getSnapshot().getTimestamp() );
    }

    @Test
    void mergeLegacyWithSnapshotLegacy()
    {
        Metadata source = createMetadataFromArtifact( artifact );
        Date before = new Date( System.currentTimeMillis() - 5000 );
        Date after = new Date( System.currentTimeMillis() );
        // legacy metadata did not have "versioning.snapshotVersions"
        addSnapshotVersionLegacy( target.getVersioning(), before, 1 );
        addSnapshotVersionLegacy( source.getVersioning(), after, 2 );
        // although nothing has changed merge returns true, as the last modified date is equal
        // TODO: improve merge here?
        assertTrue( target.merge( source ) );
        assertEquals( 0, target.getVersioning().getSnapshotVersions().size() );
        assertEquals( formatDate( after, false ), target.getVersioning().getLastUpdated() );
        assertEquals( formatDate( after, true ), target.getVersioning().getSnapshot().getTimestamp() );
    }

    @Test
    void mergeLegacyWithSnapshot()
    {
        Metadata source = createMetadataFromArtifact( artifact );
        Date before = new Date( System.currentTimeMillis() - 5000 );
        Date after = new Date( System.currentTimeMillis() );
        // legacy metadata did not have "versioning.snapshotVersions"
        addSnapshotVersionLegacy( target.getVersioning(), before, 1 );
        addSnapshotVersion( source.getVersioning(), after, artifact );
        // although nothing has changed merge returns true, as the last modified date is equal
        // TODO: improve merge here?
        assertTrue( target.merge( source ) );
        // never convert from legacy format to v1.1 format
        assertEquals( 0, target.getVersioning().getSnapshotVersions().size() );
        assertEquals( formatDate( after, false ), target.getVersioning().getLastUpdated() );
        assertEquals( formatDate( after, true ), target.getVersioning().getSnapshot().getTimestamp() );
    }

    @Test
    void mergeWithSnapshotLegacy()
    {
        Metadata source = createMetadataFromArtifact( artifact );
        Date before = new Date( System.currentTimeMillis() - 5000 );
        Date after = new Date( System.currentTimeMillis() );
        addSnapshotVersion( target.getVersioning(), before, artifact );
        // legacy metadata did not have "versioning.snapshotVersions"
        addSnapshotVersionLegacy( source.getVersioning(), after, 2 );
        // although nothing has changed merge returns true, as the last modified date is equal
        // TODO: improve merge here?
        assertTrue( target.merge( source ) );
        // the result must be legacy format as well
        assertEquals( 0, target.getVersioning().getSnapshotVersions().size() );
        assertEquals( formatDate( after, false ), target.getVersioning().getLastUpdated() );
        assertEquals( formatDate( after, true ), target.getVersioning().getSnapshot().getTimestamp() );
        assertEquals( 2, target.getVersioning().getSnapshot().getBuildNumber() );
    }
    /*-- END test "groupId/artifactId/version" metadata ---*/

    /*-- START helper methods to populate metadata objects ---*/
    private static final String SNAPSHOT = "SNAPSHOT";

    private static final String DEFAULT_SNAPSHOT_TIMESTAMP_FORMAT = "yyyyMMdd.HHmmss";

    private static final String DEFAULT_DATE_FORMAT = "yyyyMMddHHmmss";

    private static String formatDate( Date date, boolean forSnapshotTimestamp )
    {
        // logic from metadata.mdo, class "Versioning"
        TimeZone timezone = TimeZone.getTimeZone( "UTC" );
        DateFormat fmt =
            new SimpleDateFormat( forSnapshotTimestamp ? DEFAULT_SNAPSHOT_TIMESTAMP_FORMAT : DEFAULT_DATE_FORMAT );
        fmt.setCalendar( new GregorianCalendar() );
        fmt.setTimeZone( timezone );
        return fmt.format( date );
    }

    private static Metadata createMetadataFromArtifact( Artifact artifact )
    {
        Metadata metadata = new Metadata();
        metadata.setArtifactId( artifact.getArtifactId() );
        metadata.setGroupId( artifact.getGroupId() );
        metadata.setVersion( artifact.getVersion() );
        metadata.setVersioning( new Versioning() );
        return metadata;
    }

    private static SnapshotVersion addSnapshotVersion( Versioning versioning, Date timestamp, Artifact artifact )
    {
        int buildNumber = 1;
        // this generates timestamped versions like maven-resolver-provider:
        // https://github.com/apache/maven/blob/03df5f7c639db744a3597c7175c92c8e2a27767b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/RemoteSnapshotMetadata.java#L79
        String version = artifact.getVersion();
        String qualifier = formatDate( timestamp, true ) + '-' + buildNumber;
        version = version.substring( 0, version.length() - SNAPSHOT.length() ) + qualifier;
        return addSnapshotVersion( versioning, artifact.getExtension(), timestamp, version, buildNumber );
    }

    private static SnapshotVersion addSnapshotVersion( Versioning versioning, String extension, Date timestamp,
                                                       String version, int buildNumber )
    {
        Snapshot snapshot = new Snapshot();
        snapshot.setBuildNumber( buildNumber );
        snapshot.setTimestamp( formatDate( timestamp, true ) );

        SnapshotVersion sv = new SnapshotVersion();
        sv.setExtension( extension );
        sv.setVersion( version );
        sv.setUpdated( formatDate( timestamp, false ) );
        versioning.addSnapshotVersion( sv );

        // make the new snapshot the current one
        versioning.setSnapshot( snapshot );
        versioning.setLastUpdatedTimestamp( timestamp );
        return sv;
    }

    // the format written by Maven 2
    // (https://maven.apache.org/ref/2.2.1/maven-repository-metadata/repository-metadata.html)
    private static void addSnapshotVersionLegacy( Versioning versioning, Date timestamp, int buildNumber )
    {
        Snapshot snapshot = new Snapshot();
        snapshot.setBuildNumber( buildNumber );
        snapshot.setTimestamp( formatDate( timestamp, true ) );

        versioning.setSnapshot( snapshot );
        versioning.setLastUpdatedTimestamp( timestamp );
    }
    /*-- END helper methods to populate metadata objects ---*/
}