/*
 * 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 org.apache.nifi.registry.service.extension;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.apache.nifi.registry.bucket.Bucket;
import org.apache.nifi.registry.db.entity.BucketEntity;
import org.apache.nifi.registry.db.entity.ExtensionBundleEntity;
import org.apache.nifi.registry.db.entity.ExtensionBundleEntityType;
import org.apache.nifi.registry.db.entity.ExtensionBundleVersionDependencyEntity;
import org.apache.nifi.registry.db.entity.ExtensionBundleVersionEntity;
import org.apache.nifi.registry.exception.ResourceNotFoundException;
import org.apache.nifi.registry.extension.BundleCoordinate;
import org.apache.nifi.registry.extension.BundleDetails;
import org.apache.nifi.registry.extension.BundleExtractor;
import org.apache.nifi.registry.extension.ExtensionBundle;
import org.apache.nifi.registry.extension.ExtensionBundleContext;
import org.apache.nifi.registry.extension.ExtensionBundlePersistenceProvider;
import org.apache.nifi.registry.extension.ExtensionBundleType;
import org.apache.nifi.registry.extension.ExtensionBundleVersion;
import org.apache.nifi.registry.extension.ExtensionBundleVersionDependency;
import org.apache.nifi.registry.extension.ExtensionBundleVersionMetadata;
import org.apache.nifi.registry.extension.filter.ExtensionBundleFilterParams;
import org.apache.nifi.registry.extension.filter.ExtensionBundleVersionFilterParams;
import org.apache.nifi.registry.extension.repo.ExtensionRepoArtifact;
import org.apache.nifi.registry.extension.repo.ExtensionRepoBucket;
import org.apache.nifi.registry.extension.repo.ExtensionRepoGroup;
import org.apache.nifi.registry.extension.repo.ExtensionRepoVersionSummary;
import org.apache.nifi.registry.properties.NiFiRegistryProperties;
import org.apache.nifi.registry.provider.extension.StandardExtensionBundleContext;
import org.apache.nifi.registry.security.authorization.user.NiFiUserUtils;
import org.apache.nifi.registry.service.DataModelMapper;
import org.apache.nifi.registry.service.MetadataService;
import org.apache.nifi.registry.util.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validator;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
public class StandardExtensionService implements ExtensionService {

    private static final Logger LOGGER = LoggerFactory.getLogger(StandardExtensionService.class);

    static final String SNAPSHOT_VERSION_SUFFIX = "SNAPSHOT";

    private final MetadataService metadataService;
    private final Map<ExtensionBundleType, BundleExtractor> extractors;
    private final ExtensionBundlePersistenceProvider bundlePersistenceProvider;
    private final Validator validator;
    private final File extensionsWorkingDir;

    @Autowired
    public StandardExtensionService(final MetadataService metadataService,
                                    final Map<ExtensionBundleType, BundleExtractor> extractors,
                                    final ExtensionBundlePersistenceProvider bundlePersistenceProvider,
                                    final Validator validator,
                                    final NiFiRegistryProperties properties) {
        this.metadataService = metadataService;
        this.extractors = extractors;
        this.bundlePersistenceProvider = bundlePersistenceProvider;
        this.validator = validator;
        this.extensionsWorkingDir = properties.getExtensionsWorkingDirectory();
        Validate.notNull(this.metadataService);
        Validate.notNull(this.extractors);
        Validate.notNull(this.bundlePersistenceProvider);
        Validate.notNull(this.validator);
        Validate.notNull(this.extensionsWorkingDir);
    }

    private <T>  void validate(T t, String invalidMessage) {
        final Set<ConstraintViolation<T>> violations = validator.validate(t);
        if (violations.size() > 0) {
            throw new ConstraintViolationException(invalidMessage, violations);
        }
    }

    @Override
    public ExtensionBundleVersion createExtensionBundleVersion(final String bucketIdentifier, final ExtensionBundleType bundleType,
                                                               final InputStream inputStream, final String clientSha256) throws IOException {
        if (StringUtils.isBlank(bucketIdentifier)) {
            throw new IllegalArgumentException("Bucket identifier cannot be null or blank");
        }

        if (bundleType == null) {
            throw new IllegalArgumentException("Bundle type cannot be null");
        }

        if (inputStream == null) {
            throw new IllegalArgumentException("Extension bundle input stream cannot be null");
        }

        if (!extractors.containsKey(bundleType)) {
            throw new IllegalArgumentException("No metadata extractor is registered for bundle-type: " + bundleType);
        }

        // ensure the bucket exists
        final BucketEntity existingBucket = metadataService.getBucketById(bucketIdentifier);
        if (existingBucket == null) {
            LOGGER.warn("The specified bucket id [{}] does not exist.", bucketIdentifier);
            throw new ResourceNotFoundException("The specified bucket ID does not exist in this registry.");
        }

        // ensure the extensions directory exists and we can read and write to it
        FileUtils.ensureDirectoryExistAndCanReadAndWrite(extensionsWorkingDir);

        final String extensionWorkingFilename = UUID.randomUUID().toString();
        final File extensionWorkingFile = new File(extensionsWorkingDir, extensionWorkingFilename);
        LOGGER.debug("Writing bundle contents to working directory at {}", new Object[]{extensionWorkingFile.getAbsolutePath()});

        try {
            // write the contents of the input stream to a temporary file in the extensions working directory
            final MessageDigest sha256Digest = DigestUtils.getSha256Digest();
            try (final DigestInputStream digestInputStream = new DigestInputStream(inputStream, sha256Digest);
                 final OutputStream out = new FileOutputStream(extensionWorkingFile)) {
                IOUtils.copy(digestInputStream, out);
            }

            // get the hex of the SHA-256 computed by the server and compare to the client provided SHA-256, if one was provided
            final String sha256Hex = Hex.encodeHexString(sha256Digest.digest());
            final boolean sha256Supplied = !StringUtils.isBlank(clientSha256);
            if (sha256Supplied && !sha256Hex.equalsIgnoreCase(clientSha256)) {
                LOGGER.error("Client provided SHA-256 of '{}', but server calculated '{}'", new Object[]{clientSha256, sha256Hex});
                throw new IllegalStateException("The SHA-256 of the received extension bundle does not match the SHA-256 provided by the client");
            }

            // extract the details of the bundle from the temp file in the working directory
            final BundleDetails bundleDetails;
            try (final InputStream in = new FileInputStream(extensionWorkingFile)) {
                final BundleExtractor extractor = extractors.get(bundleType);
                bundleDetails = extractor.extract(in);
            }

            final BundleCoordinate bundleCoordinate = bundleDetails.getBundleCoordinate();
            final Set<BundleCoordinate> dependencyCoordinates = bundleDetails.getDependencyBundleCoordinates();

            final String groupId = bundleCoordinate.getGroupId();
            final String artifactId = bundleCoordinate.getArtifactId();
            final String version = bundleCoordinate.getVersion();

            final boolean isSnapshotVersion = version.endsWith(SNAPSHOT_VERSION_SUFFIX);
            final boolean overwriteBundleVersion = isSnapshotVersion || existingBucket.isAllowExtensionBundleRedeploy();

            LOGGER.debug("Extracted bundle details - '{}' - '{}' - '{}'", new Object[]{groupId, artifactId, version});

            // a bundle with the same group, artifact, and version can exist in multiple buckets, but only if it contains the same binary content, or if its a snapshot version
            // we can determine that by comparing the SHA-256 digest of the incoming bundle against existing bundles with the same group, artifact, version
            final List<ExtensionBundleVersionEntity> allExistingVersions = metadataService.getExtensionBundleVersionsGlobal(groupId, artifactId, version);
            for (final ExtensionBundleVersionEntity existingVersionEntity : allExistingVersions) {
                if (!existingVersionEntity.getSha256Hex().equals(sha256Hex) && !isSnapshotVersion) {
                    throw new IllegalStateException("Found existing extension bundle with same group, artifact, and version, but different SHA-256 checksums");
                }
            }

            // get the existing extension bundle entity, or create a new one if one does not exist in the bucket with the group + artifact
            final long currentTime = System.currentTimeMillis();
            final ExtensionBundleEntity extensionBundle = getOrCreateExtensionBundle(bucketIdentifier, groupId, artifactId, bundleType, currentTime);

            // check if the version of incoming bundle already exists in the bucket
            // if it exists and it is a snapshot version or the bucket allows redeploying, then first delete the row in the extension_bundle_version table so we can create a new one
            // otherwise we throw an exception because we don't allow the same version in the same bucket
            final ExtensionBundleVersionEntity existingVersion = metadataService.getExtensionBundleVersion(bucketIdentifier, groupId, artifactId, version);
            if (existingVersion != null) {
                if (overwriteBundleVersion) {
                    metadataService.deleteExtensionBundleVersion(existingVersion);
                } else {
                    LOGGER.warn("The specified version [{}] already exists for extension bundle [{}].", new Object[]{version, extensionBundle.getId()});
                    throw new IllegalStateException("The specified version already exists for the given extension bundle");
                }
            }

            // create the version metadata instance and validate it has all the required fields
            final String userIdentity = NiFiUserUtils.getNiFiUserIdentity();
            final ExtensionBundleVersionMetadata versionMetadata = new ExtensionBundleVersionMetadata();
            versionMetadata.setId(UUID.randomUUID().toString());
            versionMetadata.setExtensionBundleId(extensionBundle.getId());
            versionMetadata.setBucketId(bucketIdentifier);
            versionMetadata.setVersion(version);
            versionMetadata.setTimestamp(currentTime);
            versionMetadata.setAuthor(userIdentity);
            versionMetadata.setSha256(sha256Hex);
            versionMetadata.setSha256Supplied(sha256Supplied);
            versionMetadata.setContentSize(extensionWorkingFile.length());

            validate(versionMetadata, "Cannot create extension bundle version");

            // create the version dependency instances and validate they have the required fields
            final Set<ExtensionBundleVersionDependency> versionDependencies = new HashSet<>();
            for (final BundleCoordinate dependencyCoordinate : dependencyCoordinates) {
                final ExtensionBundleVersionDependency versionDependency = new ExtensionBundleVersionDependency();
                versionDependency.setGroupId(dependencyCoordinate.getGroupId());
                versionDependency.setArtifactId(dependencyCoordinate.getArtifactId());
                versionDependency.setVersion(dependencyCoordinate.getVersion());

                validate(versionDependency, "Cannot create extension bundle version dependency");
                versionDependencies.add(versionDependency);
            }

            // create the bundle version in the metadata db
            final ExtensionBundleVersionEntity versionEntity = DataModelMapper.map(versionMetadata);
            metadataService.createExtensionBundleVersion(versionEntity);

            // create the bundle version dependencies in the metadata db
            for (final ExtensionBundleVersionDependency versionDependency : versionDependencies) {
                final ExtensionBundleVersionDependencyEntity versionDependencyEntity = DataModelMapper.map(versionDependency);
                versionDependencyEntity.setId(UUID.randomUUID().toString());
                versionDependencyEntity.setExtensionBundleVersionId(versionEntity.getId());
                metadataService.createDependency(versionDependencyEntity);
            }

            // persist the content of the bundle to the persistence provider
            final ExtensionBundleContext context = new StandardExtensionBundleContext.Builder()
                    .bundleType(getProviderBundleType(bundleType))
                    .bucketId(existingBucket.getId())
                    .bucketName(existingBucket.getName())
                    .bundleId(extensionBundle.getId())
                    .bundleGroupId(extensionBundle.getGroupId())
                    .bundleArtifactId(extensionBundle.getArtifactId())
                    .bundleVersion(versionMetadata.getVersion())
                    .author(versionMetadata.getAuthor())
                    .timestamp(versionMetadata.getTimestamp())
                    .build();

            try (final InputStream in = new FileInputStream(extensionWorkingFile);
                 final InputStream bufIn = new BufferedInputStream(in)) {
                bundlePersistenceProvider.saveBundleVersion(context, bufIn, overwriteBundleVersion);
                LOGGER.debug("Bundle saved to persistence provider - '{}' - '{}' - '{}'", new Object[]{groupId, artifactId, version});
            }

            // get the updated extension bundle so it contains the correct version count
            final ExtensionBundleEntity updatedBundle = metadataService.getExtensionBundle(bucketIdentifier, groupId, artifactId);

            // create the full ExtensionBundleVersion instance to return
            final ExtensionBundleVersion extensionBundleVersion = new ExtensionBundleVersion();
            extensionBundleVersion.setVersionMetadata(versionMetadata);
            extensionBundleVersion.setExtensionBundle(DataModelMapper.map(existingBucket, updatedBundle));
            extensionBundleVersion.setBucket(DataModelMapper.map(existingBucket));
            extensionBundleVersion.setDependencies(versionDependencies);
            return extensionBundleVersion;

        } finally {
            if (extensionWorkingFile.exists()) {
                try {
                    extensionWorkingFile.delete();
                } catch (Exception e) {
                    LOGGER.warn("Error removing temporary extension bundle file at {}",
                            new Object[]{extensionWorkingFile.getAbsolutePath()});
                }
            }
        }
    }

    private ExtensionBundleEntity getOrCreateExtensionBundle(final String bucketId, final String groupId,
                                                             final String artifactId, final ExtensionBundleType bundleType,
                                                             final long currentTime) {
        ExtensionBundleEntity existingBundleEntity = metadataService.getExtensionBundle(bucketId, groupId, artifactId);
        if (existingBundleEntity == null) {
            final ExtensionBundle bundle = new ExtensionBundle();
            bundle.setIdentifier(UUID.randomUUID().toString());
            bundle.setBucketIdentifier(bucketId);
            bundle.setName(groupId + ":" + artifactId);
            bundle.setGroupId(groupId);
            bundle.setArtifactId(artifactId);
            bundle.setBundleType(bundleType);
            bundle.setCreatedTimestamp(currentTime);
            bundle.setModifiedTimestamp(currentTime);

            validate(bundle, "Cannot create extension bundle");
            existingBundleEntity = metadataService.createExtensionBundle(DataModelMapper.map(bundle));
        } else {
            final ExtensionBundleEntityType bundleEntityType = DataModelMapper.map(bundleType);
            if (bundleEntityType != existingBundleEntity.getBundleType()) {
                throw new IllegalStateException("A bundle already exists with the same group id and artifact id, but a different bundle type");
            }
        }

        return existingBundleEntity;
    }

    private ExtensionBundleContext.BundleType getProviderBundleType(final ExtensionBundleType bundleType) {
        switch (bundleType) {
            case NIFI_NAR:
                return ExtensionBundleContext.BundleType.NIFI_NAR;
            case MINIFI_CPP:
                return ExtensionBundleContext.BundleType.MINIFI_CPP;
            default:
                throw new IllegalArgumentException("Unknown bundle type: " + bundleType.toString());
        }
    }

    @Override
    public List<ExtensionBundle> getExtensionBundles(final Set<String> bucketIdentifiers, final ExtensionBundleFilterParams filterParams) {
        if (bucketIdentifiers == null) {
            throw new IllegalArgumentException("Bucket identifiers cannot be null");
        }

        final List<ExtensionBundleEntity> bundleEntities = metadataService.getExtensionBundles(bucketIdentifiers,
                filterParams == null ? ExtensionBundleFilterParams.empty() : filterParams);
        return bundleEntities.stream().map(b -> DataModelMapper.map(null, b)).collect(Collectors.toList());
    }

    @Override
    public List<ExtensionBundle> getExtensionBundlesByBucket(final String bucketIdentifier) {
        if (StringUtils.isBlank(bucketIdentifier)) {
            throw new IllegalArgumentException("Bucket identifier cannot be null or blank");
        }

        // ensure the bucket exists
        final BucketEntity existingBucket = metadataService.getBucketById(bucketIdentifier);
        if (existingBucket == null) {
            LOGGER.warn("The specified bucket id [{}] does not exist.", bucketIdentifier);
            throw new ResourceNotFoundException("The specified bucket ID does not exist in this registry.");
        }

        final List<ExtensionBundleEntity> bundleEntities = metadataService.getExtensionBundlesByBucket(bucketIdentifier);
        return bundleEntities.stream().map(b -> DataModelMapper.map(existingBucket, b)).collect(Collectors.toList());
    }

    @Override
    public ExtensionBundle getExtensionBundle(final String extensionBundleIdentifier) {
        if (StringUtils.isBlank(extensionBundleIdentifier)) {
            throw new IllegalArgumentException("Extension bundle identifier cannot be null or blank");
        }

        final ExtensionBundleEntity existingBundle = metadataService.getExtensionBundle(extensionBundleIdentifier);
        if (existingBundle == null) {
            LOGGER.warn("The specified extension bundle id [{}] does not exist.", extensionBundleIdentifier);
            throw new ResourceNotFoundException("The specified extension bundle ID does not exist.");
        }

        final BucketEntity existingBucket = metadataService.getBucketById(existingBundle.getBucketId());
        return DataModelMapper.map(existingBucket, existingBundle);
    }

    @Override
    public ExtensionBundle deleteExtensionBundle(final ExtensionBundle extensionBundle) {
        if (extensionBundle == null) {
            throw new IllegalArgumentException("Extension bundle cannot be null");
        }

        // delete the bundle from the database
        metadataService.deleteExtensionBundle(extensionBundle.getIdentifier());

        // delete all content associated with the bundle in the persistence provider
        bundlePersistenceProvider.deleteAllBundleVersions(
                extensionBundle.getBucketIdentifier(),
                extensionBundle.getBucketName(),
                extensionBundle.getGroupId(),
                extensionBundle.getArtifactId());

        return extensionBundle;
    }

    @Override
    public SortedSet<ExtensionBundleVersionMetadata> getExtensionBundleVersions(final Set<String> bucketIdentifiers,
                                                                                final ExtensionBundleVersionFilterParams filterParams) {
        if (bucketIdentifiers == null) {
            throw new IllegalArgumentException("Bucket identifiers cannot be null");
        }

        final SortedSet<ExtensionBundleVersionMetadata> sortedVersions = new TreeSet<>(
                Comparator.comparing(ExtensionBundleVersionMetadata::getExtensionBundleId)
                        .thenComparing(ExtensionBundleVersionMetadata::getVersion)
        );

        final List<ExtensionBundleVersionEntity> bundleVersionEntities = metadataService.getExtensionBundleVersions(bucketIdentifiers,
                filterParams == null ? ExtensionBundleVersionFilterParams.empty() : filterParams);
        if (bundleVersionEntities != null) {
            bundleVersionEntities.forEach(bv -> sortedVersions.add(DataModelMapper.map(bv)));
        }
        return sortedVersions;
    }

    @Override
    public SortedSet<ExtensionBundleVersionMetadata> getExtensionBundleVersions(final String extensionBundleIdentifier) {
        if (StringUtils.isBlank(extensionBundleIdentifier)) {
            throw new IllegalArgumentException("Extension bundle identifier cannot be null or blank");
        }

        // ensure the bundle exists
        final ExtensionBundleEntity existingBundle = metadataService.getExtensionBundle(extensionBundleIdentifier);
        if (existingBundle == null) {
            LOGGER.warn("The specified extension bundle id [{}] does not exist.", extensionBundleIdentifier);
            throw new ResourceNotFoundException("The specified extension bundle ID does not exist in this bucket.");
        }

        return getExtensionBundleVersionsSet(existingBundle);
    }

    private SortedSet<ExtensionBundleVersionMetadata> getExtensionBundleVersionsSet(final ExtensionBundleEntity existingBundle) {
        final SortedSet<ExtensionBundleVersionMetadata> sortedVersions = new TreeSet<>(Collections.reverseOrder());

        final List<ExtensionBundleVersionEntity> existingVersions = metadataService.getExtensionBundleVersions(existingBundle.getId());
        if (existingVersions != null) {
            existingVersions.stream().forEach(s -> sortedVersions.add(DataModelMapper.map(s)));
        }
        return sortedVersions;
    }

    @Override
    public ExtensionBundleVersion getExtensionBundleVersion(ExtensionBundleVersionCoordinate versionCoordinate) {
        if (versionCoordinate == null) {
            throw new IllegalArgumentException("Extension bundle version coordinate cannot be null");
        }

        // ensure the bucket exists
        final BucketEntity existingBucket = metadataService.getBucketById(versionCoordinate.getBucketId());
        if (existingBucket == null) {
            LOGGER.warn("The specified bucket id [{}] does not exist.", versionCoordinate.getBucketId());
            throw new ResourceNotFoundException("The specified bucket ID does not exist in this registry.");
        }

        // ensure the bundle exists
        final ExtensionBundleEntity existingBundle = metadataService.getExtensionBundle(
                versionCoordinate.getBucketId(),
                versionCoordinate.getGroupId(),
                versionCoordinate.getArtifactId());

        if (existingBundle == null) {
            LOGGER.warn("The specified extension bundle [{}] does not exist.", versionCoordinate.toString());
            throw new ResourceNotFoundException("The specified extension bundle does not exist in this bucket.");
        }

        //ensure the version of the bundle exists
        final ExtensionBundleVersionEntity existingVersion = metadataService.getExtensionBundleVersion(
                versionCoordinate.getBucketId(),
                versionCoordinate.getGroupId(),
                versionCoordinate.getArtifactId(),
                versionCoordinate.getVersion());

        if (existingVersion == null) {
            LOGGER.warn("The specified extension bundle version [{}] does not exist.", versionCoordinate.toString());
            throw new ResourceNotFoundException("The specified extension bundle version does not exist in this bucket.");
        }

        // get the dependencies for the bundle version
        final List<ExtensionBundleVersionDependencyEntity> existingVersionDependencies = metadataService
                .getDependenciesForBundleVersion(existingVersion.getId());

        // convert the dependency db entities
        final Set<ExtensionBundleVersionDependency> dependencies = existingVersionDependencies.stream()
                .map(d -> DataModelMapper.map(d))
                .collect(Collectors.toSet());

        // create the full ExtensionBundleVersion instance to return
        final ExtensionBundleVersion extensionBundleVersion = new ExtensionBundleVersion();
        extensionBundleVersion.setVersionMetadata(DataModelMapper.map(existingVersion));
        extensionBundleVersion.setExtensionBundle(DataModelMapper.map(existingBucket, existingBundle));
        extensionBundleVersion.setBucket(DataModelMapper.map(existingBucket));
        extensionBundleVersion.setDependencies(dependencies);
        return extensionBundleVersion;
    }

    @Override
    public void writeExtensionBundleVersionContent(final ExtensionBundleVersion bundleVersion, final OutputStream out) {
        // get the content from the persistence provider and write it to the output stream
        final ExtensionBundleContext context = getExtensionBundleContext(bundleVersion);
        bundlePersistenceProvider.getBundleVersion(context, out);
    }

    @Override
    public ExtensionBundleVersion deleteExtensionBundleVersion(final ExtensionBundleVersion bundleVersion) {
        if (bundleVersion == null) {
            throw new IllegalArgumentException("Extension bundle version cannot be null");
        }

        // delete from the metadata db
        final String extensionBundleVersionId = bundleVersion.getVersionMetadata().getId();
        metadataService.deleteExtensionBundleVersion(extensionBundleVersionId);

        // delete content associated with the bundle version in the persistence provider
        final ExtensionBundleContext context = new StandardExtensionBundleContext.Builder()
                .bundleType(getProviderBundleType(bundleVersion.getExtensionBundle().getBundleType()))
                .bucketId(bundleVersion.getBucket().getIdentifier())
                .bucketName(bundleVersion.getBucket().getName())
                .bundleId(bundleVersion.getExtensionBundle().getIdentifier())
                .bundleGroupId(bundleVersion.getExtensionBundle().getGroupId())
                .bundleArtifactId(bundleVersion.getExtensionBundle().getArtifactId())
                .bundleVersion(bundleVersion.getVersionMetadata().getVersion())
                .author(bundleVersion.getVersionMetadata().getAuthor())
                .timestamp(bundleVersion.getVersionMetadata().getTimestamp())
                .build();

        bundlePersistenceProvider.deleteBundleVersion(context);

        return bundleVersion;
    }

    // ------ Extension Repository Methods -------

    @Override
    public SortedSet<ExtensionRepoBucket> getExtensionRepoBuckets(final Set<String> bucketIds) {
        if (bucketIds == null) {
            throw new IllegalArgumentException("Bucket ids cannot be null");
        }

        if (bucketIds.isEmpty()) {
            return new TreeSet<>();
        }

        final SortedSet<ExtensionRepoBucket> repoBuckets = new TreeSet<>();

        final List<BucketEntity> buckets = metadataService.getBuckets(bucketIds);
        buckets.forEach(b -> {
            final ExtensionRepoBucket repoBucket = new ExtensionRepoBucket();
            repoBucket.setBucketName(b.getName());
            repoBuckets.add(repoBucket);
        });

        return repoBuckets;
    }

    @Override
    public SortedSet<ExtensionRepoGroup> getExtensionRepoGroups(final Bucket bucket) {
        if (bucket == null) {
            throw new IllegalArgumentException("Bucket cannot be null");
        }

        final SortedSet<ExtensionRepoGroup> repoGroups = new TreeSet<>();

        final List<ExtensionBundleEntity> bundleEntities = metadataService.getExtensionBundlesByBucket(bucket.getIdentifier());
        bundleEntities.forEach(b -> {
            final ExtensionRepoGroup repoGroup = new ExtensionRepoGroup();
            repoGroup.setBucketName(bucket.getName());
            repoGroup.setGroupId(b.getGroupId());
            repoGroups.add(repoGroup);
        });

        return repoGroups;
    }

    @Override
    public SortedSet<ExtensionRepoArtifact> getExtensionRepoArtifacts(final Bucket bucket, final String groupId) {
        if (bucket == null) {
            throw new IllegalArgumentException("Bucket cannot be null");
        }

        if (StringUtils.isBlank(groupId)) {
            throw new IllegalArgumentException("Group id cannot be null or blank");
        }

        final SortedSet<ExtensionRepoArtifact> repoArtifacts = new TreeSet<>();

        final List<ExtensionBundleEntity> bundleEntities = metadataService.getExtensionBundlesByBucketAndGroup(bucket.getIdentifier(), groupId);
        bundleEntities.forEach(b -> {
            final ExtensionRepoArtifact repoArtifact = new ExtensionRepoArtifact();
            repoArtifact.setBucketName(bucket.getName());
            repoArtifact.setGroupId(b.getGroupId());
            repoArtifact.setArtifactId(b.getArtifactId());
            repoArtifacts.add(repoArtifact);
        });

        return repoArtifacts;
    }

    @Override
    public SortedSet<ExtensionRepoVersionSummary> getExtensionRepoVersions(final Bucket bucket, final String groupId, final String artifactId) {
        if (bucket == null) {
            throw new IllegalArgumentException("Bucket cannot be null");
        }

        if (StringUtils.isBlank(groupId)) {
            throw new IllegalArgumentException("Group id cannot be null or blank");
        }

        if (StringUtils.isBlank(artifactId)) {
            throw new IllegalArgumentException("Artifact id cannot be null or blank");
        }

        final SortedSet<ExtensionRepoVersionSummary> repoVersions = new TreeSet<>();

        final List<ExtensionBundleVersionEntity> versionEntities = metadataService.getExtensionBundleVersions(bucket.getIdentifier(), groupId, artifactId);
        if (!versionEntities.isEmpty()) {
            final ExtensionBundleEntity bundleEntity = metadataService.getExtensionBundle(bucket.getIdentifier(), groupId, artifactId);
            if (bundleEntity == null) {
                // should never happen if the list of versions is not empty, but just in case
                throw new ResourceNotFoundException("The specified extension bundle does not exist in this bucket");
            }

            versionEntities.forEach(v -> {
                final ExtensionRepoVersionSummary repoVersion = new ExtensionRepoVersionSummary();
                repoVersion.setBucketName(bucket.getName());
                repoVersion.setGroupId(bundleEntity.getGroupId());
                repoVersion.setArtifactId(bundleEntity.getArtifactId());
                repoVersion.setVersion(v.getVersion());
                repoVersions.add(repoVersion);
            });
        }

        return repoVersions;
    }

    // ------ Helper Methods -------

    private ExtensionBundleContext getExtensionBundleContext(final ExtensionBundleVersion bundleVersion) {
        return getExtensionBundleContext(bundleVersion.getBucket(), bundleVersion.getExtensionBundle(), bundleVersion.getVersionMetadata());
    }

    private ExtensionBundleContext getExtensionBundleContext(final Bucket bucket, final ExtensionBundle bundle,
                                                             final ExtensionBundleVersionMetadata bundleVersionMetadata) {
        return new StandardExtensionBundleContext.Builder()
                .bundleType(getProviderBundleType(bundle.getBundleType()))
                .bucketId(bucket.getIdentifier())
                .bucketName(bucket.getName())
                .bundleId(bundle.getIdentifier())
                .bundleGroupId(bundle.getGroupId())
                .bundleArtifactId(bundle.getArtifactId())
                .bundleVersion(bundleVersionMetadata.getVersion())
                .author(bundleVersionMetadata.getAuthor())
                .timestamp(bundleVersionMetadata.getTimestamp())
                .build();
    }
}
