/*
 * 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.sling.jcr.maintenance.internal;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

import javax.jcr.ItemNotFoundException;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.version.Version;
import javax.jcr.version.VersionHistory;
import javax.jcr.version.VersionIterator;
import javax.jcr.version.VersionManager;
import javax.management.DynamicMBean;

import org.apache.jackrabbit.oak.commons.jmx.AnnotatedStandardMBean;
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.jcr.maintenance.VersionCleanupConfig;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.ConfigurationPolicy;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicyOption;
import org.osgi.service.metatype.annotations.Designate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 
 */
@Component(service = { VersionCleanupMBean.class, Runnable.class, DynamicMBean.class }, property = {
        "jmx.objectname=org.apache.sling.jcr.maintenance:type=VersionCleanup",
        "scheduler.concurrent:Boolean=false" }, configurationPolicy = ConfigurationPolicy.REQUIRE, immediate = true)
@Designate(ocd = VersionCleanupConfig.class)
public class VersionCleanup extends AnnotatedStandardMBean implements Runnable, VersionCleanupMBean {

    private static final Logger log = LoggerFactory.getLogger(VersionCleanup.class);

    private Thread cleanupThread;
    private final ResourceResolverFactory factory;
    private long lastCleanedVersions;
    private String lastFailureMessage;
    private final List<VersionCleanupPath> versionCleanupConfigs;

    @Activate
    public VersionCleanup(
            @Reference(cardinality = ReferenceCardinality.AT_LEAST_ONE, policyOption = ReferencePolicyOption.GREEDY) final List<VersionCleanupPath> versionCleanupConfigs,
            @Reference final ResourceResolverFactory factory) {
        super(VersionCleanupMBean.class);
        this.factory = factory;
        this.versionCleanupConfigs = versionCleanupConfigs;
        versionCleanupConfigs.sort((c1, c2) -> c1.getPath().compareTo(c2.getPath()) * -1);

    }

    private String getPath(final Session session, final VersionHistory versionHistory) throws RepositoryException {
        String identifier = versionHistory.getVersionableIdentifier();
        try {
            Node versionableNode = session.getNodeByIdentifier(identifier);
            return versionableNode.getPath();
        } catch (ItemNotFoundException infe) {
            log.debug("Unable to get versionable node by ID: {}, exception: {}", identifier, infe.getMessage());
            return versionHistory.getProperty(session.getWorkspace().getName()).getString();
        }
    }

    private void cleanupVersions(final Session session, final Resource history) {
        try {
            final VersionHistory versionHistory = (VersionHistory) session.getItem(history.getPath());
            final String path = getPath(session, versionHistory);
            final VersionCleanupPath config = VersionCleanupPath.getMatchingConfiguration(this.versionCleanupConfigs,
                    path);
            int limit = config.getLimit();

            if (!isMatchingVersion(session, path, versionHistory) && !config.isKeepVersions() && limit > 0) {
                log.debug("Deleted, removing all but last version");
                limit = 1;
            }
            log.debug("Cleaning up versions for: {}", versionHistory.getPath());
            final VersionIterator versionIterator = versionHistory.getAllVersions();
            final List<String> versionNames = new ArrayList<>();
            while (versionIterator.hasNext()) {
                final Version version = versionIterator.nextVersion();
                if (!version.getName().equals("jcr:rootVersion")) {
                    versionNames.add(version.getName());
                }
            }
            if (versionNames.size() > limit) {
                final List<String> toCleanup = versionNames.subList(0, versionNames.size() - limit);
                log.info("Cleaning up {} versions from {} at: {}", toCleanup.size(), path, versionHistory.getPath());
                for (final String item : toCleanup) {
                    versionHistory.removeVersion(item);
                    log.trace("Cleaned up: {}", item);
                    lastCleanedVersions++;
                }
            }
        } catch (final RepositoryException re) {
            log.warn("Failed to cleanup version history for: {}", history.getPath(), re);
        }

    }

    private boolean findVersions(final Session session, final Resource resource) throws RepositoryException {
        if (Thread.interrupted()) {
            return true;
        }
        log.debug("Finding versions under: {}", resource.getPath());
        if ("nt:versionHistory".equals(resource.getResourceType())) {
            resource.getResourceResolver().refresh();
            cleanupVersions(session, resource);
        } else {
            for (final Resource child : resource.getChildren()) {
                if (findVersions(session, child)) {
                    return true;
                }
            }
        }
        return false;
    }

    private boolean isMatchingVersion(Session session, String path, VersionHistory versionHistory)
            throws RepositoryException {
        try {
            VersionManager versionManager = session.getWorkspace().getVersionManager();
            String baseVersionPath = versionManager.getBaseVersion(path).getParent().getPath();
            String versionHistoryPath = versionHistory.getPath();

            return session.nodeExists(path) && isVersionable(session.getNode(path))
                    && baseVersionPath.equals(versionHistoryPath);
        } catch (PathNotFoundException pnfe) {
            log.debug("Path: {} not found: {}", path, pnfe.getMessage());
            return false;
        }
    }

    private boolean isVersionable(final Node node) throws RepositoryException {
        return node != null && node.isNodeType("{http://www.jcp.org/jcr/mix/1.0}versionable");
    }

    @Override
    public void run() {
        if (isRunning()) {
            log.warn("Version cleanup already running!");
        } else {
            cleanupThread = new Thread((this::doRun));
            cleanupThread.setDaemon(true);
            cleanupThread.start();
        }
    }

    private void doRun() {
        log.info("Running version cleanup");
        lastCleanedVersions = 0;
        try {
            try (final ResourceResolver adminResolver = factory.getServiceResourceResolver(
                    Collections.singletonMap(ResourceResolverFactory.SUBSERVICE, "sling-versionmgr"))) {
                final Resource versionRoot = adminResolver.getResource("/jcr:system/jcr:versionStorage");
                final Session session = Optional.ofNullable(versionRoot.getResourceResolver().adaptTo(Session.class))
                        .orElseThrow(() -> new RepositoryException("Failed to get session"));
                for (final Resource folder : versionRoot.getChildren()) {
                    log.info("Traversing and cleaning: {}", folder.getPath());
                    if (findVersions(session, folder)) {
                        break;
                    }
                }
                lastFailureMessage = null;
            }
        } catch (final LoginException le) {
            log.error("Failed to run version cleanup, cannot get service user", le);
            lastFailureMessage = "Failed to run version cleanup, cannot get service user";
        } catch (final RepositoryException re) {
            log.error("Failed to run version cleanup", re);
            lastFailureMessage = "Failed to run version cleanup";
        }
    }

    @Override
    public boolean isRunning() {
        return cleanupThread != null && cleanupThread.isAlive();
    }

    @Override
    public boolean isFailed() {
        return lastFailureMessage != null;
    }

    @Override
    public String getLastMessage() {
        return lastFailureMessage;
    }

    @Override
    public long getLastCleanedVersionsCount() {
        return lastCleanedVersions;
    }

    @Override
    public void start() {
        this.run();
    }

    @Override
    public void stop() {
        Optional.ofNullable(cleanupThread).ifPresent(Thread::interrupt);
    }
}
