package org.apache.archiva.consumers.core.repository;

/*
 * 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 org.apache.archiva.common.utils.VersionComparator;
import org.apache.archiva.common.utils.VersionUtil;
import org.apache.archiva.metadata.repository.RepositorySession;
import org.apache.archiva.model.ArtifactReference;
import org.apache.archiva.model.VersionedReference;
import org.apache.archiva.repository.ContentNotFoundException;
import org.apache.archiva.repository.ManagedRepositoryContent;
import org.apache.archiva.repository.events.RepositoryListener;
import org.apache.archiva.repository.layout.LayoutException;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Purge the repository by retention count. Retain only the specified number of snapshots.
 */
public class RetentionCountRepositoryPurge
    extends AbstractRepositoryPurge
{
    private int retentionCount;

    public RetentionCountRepositoryPurge( ManagedRepositoryContent repository, int retentionCount,
                                          RepositorySession repositorySession, List<RepositoryListener> listeners )
    {
        super( repository, repositorySession, listeners );
        this.retentionCount = retentionCount;
    }

    @Override
    public void process( String path )
        throws RepositoryPurgeException
    {
        try
        {
            File artifactFile = new File( repository.getRepoRoot(), path );

            if ( !artifactFile.exists() )
            {
                return;
            }

            ArtifactReference artifact = repository.toArtifactReference( path );

            if ( VersionUtil.isSnapshot( artifact.getVersion() ) )
            {
                VersionedReference reference = new VersionedReference();
                reference.setGroupId( artifact.getGroupId() );
                reference.setArtifactId( artifact.getArtifactId() );
                reference.setVersion( artifact.getVersion() );

                List<String> versions = new ArrayList<>( repository.getVersions( reference ) );

                Collections.sort( versions, VersionComparator.getInstance() );

                if ( retentionCount > versions.size() )
                {
                    log.trace("No deletion, because retention count is higher than actual number of artifacts.");
                    // Done. nothing to do here. skip it.
                    return;
                }

                int countToPurge = versions.size() - retentionCount;
                Set<ArtifactReference> artifactsToDelete = new HashSet<>();
                for ( String version : versions )
                {
                    if ( countToPurge-- <= 0 )
                    {
                        break;
                    }
                    artifactsToDelete.addAll(repository.getRelatedArtifacts( getNewArtifactReference( artifact, version) ));
                }
                purge(artifactsToDelete);
            }
        }
        catch ( LayoutException le )
        {
            throw new RepositoryPurgeException( le.getMessage(), le );
        }
        catch ( ContentNotFoundException e )
        {
            log.error("Repostory artifact not found {}", path);
        }
    }

    /*
     * Returns a new artifact reference with different version
     */
    private ArtifactReference getNewArtifactReference( ArtifactReference reference, String version )
        throws LayoutException
    {
        ArtifactReference artifact = new ArtifactReference();
        artifact.setGroupId( reference.getGroupId() );
        artifact.setArtifactId( reference.getArtifactId() );
        artifact.setVersion( version );
        artifact.setClassifier( reference.getClassifier() );
        artifact.setType( reference.getType() );
        return artifact;

    }
}
