/*
 * 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.clam.oak.internal;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

import javax.jcr.Property;
import javax.jcr.PropertyType;
import javax.jcr.Session;

import org.apache.jackrabbit.oak.plugins.observation.NodeObserver;
import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
import org.apache.jackrabbit.oak.spi.commit.Observer;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.commons.threads.ThreadPool;
import org.apache.sling.commons.threads.ThreadPoolManager;
import org.apache.sling.event.jobs.JobManager;
import org.apache.sling.serviceusermapping.ServiceUserMapped;
import org.jetbrains.annotations.NotNull;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Modified;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.component.annotations.ReferencePolicyOption;
import org.osgi.service.metatype.annotations.Designate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.apache.sling.clam.internal.ClamUtil.checkLength;
import static org.apache.sling.clam.internal.ClamUtil.properties;
import static org.apache.sling.clam.internal.ClamUtil.scanJobTopic;

/**
 * Service to observe JCR nodes for matching properties.
 */
@Component(
    service = Observer.class,
    immediate = true,
    property = {
        Constants.SERVICE_DESCRIPTION + "=Apache Sling Clam Node Observing JCR Property Digger",
        Constants.SERVICE_VENDOR + "=The Apache Software Foundation"
    }
)
@Designate(
    ocd = NodeObservingJcrPropertyDiggerConfiguration.class,
    factory = true
)
@SuppressWarnings({"java:S1117", "java:S3077"})
public final class NodeObservingJcrPropertyDigger extends NodeObserver {

    @Reference(
        policy = ReferencePolicy.DYNAMIC,
        policyOption = ReferencePolicyOption.GREEDY
    )
    private volatile ResourceResolverFactory resourceResolverFactory;

    @Reference
    private volatile ThreadPoolManager threadPoolManager;

    @Reference(
        policy = ReferencePolicy.DYNAMIC,
        policyOption = ReferencePolicyOption.GREEDY
    )
    private volatile JobManager jobManager;

    @Reference(
        policy = ReferencePolicy.DYNAMIC,
        policyOption = ReferencePolicyOption.GREEDY
    )
    @SuppressWarnings("unused")
    private volatile ServiceUserMapped serviceUserMapped;

    private Pattern pattern;

    private int propertyType;

    private ThreadPool threadPool;

    private NodeObservingJcrPropertyDiggerConfiguration configuration;

    private final Logger logger = LoggerFactory.getLogger(NodeObservingJcrPropertyDigger.class);

    public NodeObservingJcrPropertyDigger() {
        super("/");
    }

    @Activate
    @SuppressWarnings("unused")
    private void activate(final NodeObservingJcrPropertyDiggerConfiguration configuration) {
        logger.debug("activating");
        this.configuration = configuration;
        configure(configuration);
        threadPool = threadPoolManager.get(configuration.threadpool_name());
    }

    @Modified
    @SuppressWarnings("unused")
    private void modified(final NodeObservingJcrPropertyDiggerConfiguration configuration) {
        logger.debug("modifying");
        this.configuration = configuration;
        configure(configuration);
    }

    @Deactivate
    @SuppressWarnings("unused")
    private void deactivate() {
        logger.debug("deactivating");
        threadPoolManager.release(threadPool);
        configuration = null;
    }

    private void configure(final NodeObservingJcrPropertyDiggerConfiguration configuration) {
        pattern = Pattern.compile(configuration.property_path_pattern());
        propertyType = PropertyType.valueFromName(configuration.property_type());
    }

    @Override
    protected void added(@NotNull final String path, @NotNull final Set<String> added, @NotNull final Set<String> deleted, @NotNull final Set<String> changed, @NotNull final Map<String, String> properties, @NotNull final CommitInfo commitInfo) {
        if (!commitInfo.isExternal()) {
            dig(path, concat(added, changed), pattern, propertyType, configuration.property_length_max(), commitInfo.getUserId());
        }
    }

    @Override
    protected void deleted(@NotNull final String path, @NotNull final Set<String> added, @NotNull final Set<String> deleted, @NotNull final Set<String> changed, @NotNull final Map<String, String> properties, @NotNull final CommitInfo commitInfo) {
        // ignoring, deleted data is not relevant
    }

    @Override
    protected void changed(@NotNull final String path, @NotNull final Set<String> added, @NotNull final Set<String> deleted, @NotNull final Set<String> changed, @NotNull final Map<String, String> properties, @NotNull final CommitInfo commitInfo) {
        dig(path, concat(added, changed), pattern, propertyType, configuration.property_length_max(), commitInfo.getUserId());
    }

    private void dig(final String path, final Set<String> names, final Pattern pattern, final int propertyType, final long maxLength, final String userId) {
        final DigTask digTask = new DigTask(path, names, pattern, propertyType, maxLength, userId);
        threadPool.submit(digTask);
    }

    private Set<String> concat(final Set<String> a, final Set<String> b) {
        final Set<String> set = new HashSet<>(a);
        set.addAll(b);
        return set;
    }

    private class DigTask implements Runnable {

        private final String path;

        private final Set<String> names;

        private final Pattern pattern;

        private final int propertyType;

        private final long maxLength;

        private final String userId;

        DigTask(final String path, final Set<String> names, final Pattern pattern, final int propertyType, final long maxLength, final String userId) {
            this.path = path;
            this.names = names;
            this.pattern = pattern;
            this.propertyType = propertyType;
            this.maxLength = maxLength;
            this.userId = userId;
        }

        private Set<String> filter(final String path, final Set<String> names, final Pattern pattern) {
            final Set<String> paths = new HashSet<>();
            for (final String name : names) {
                final String p = String.format("%s/%s", path, name);
                if (pattern.matcher(p).matches()) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("path '{}' matches pattern '{}'", p, pattern.pattern());
                    }
                    paths.add(p);
                } else {
                    if (logger.isDebugEnabled()) {
                        logger.debug("path '{}' doesn't match pattern '{}'", p, pattern.pattern());
                    }
                }
            }
            return paths;
        }

        @Override
        @SuppressWarnings({"java:S3776", "checkstyle:IllegalCatch", "checkstyle:NestedIfDepth"})
        public void run() {
            final Set<String> paths = filter(path, names, pattern);
            try (ResourceResolver resourceResolver = resourceResolverFactory.getServiceResourceResolver(null)) {
                final Session session = resourceResolver.adaptTo(Session.class);
                assert session != null;
                for (final String path : paths) {
                    final Property property = session.getProperty(path);
                    final int propertyType = property.getType();
                    if (propertyType == this.propertyType) {
                        if (property.isMultiple()) { // multiple property values
                            final long[] lengths = property.getLengths();
                            for (int index = 0; index < lengths.length; index++) {
                                final long length = lengths[index];
                                if (checkLength(length, maxLength)) {
                                    jobManager.addJob(scanJobTopic(propertyType), properties(path, index, userId));
                                } else {
                                    logger.warn("Length of property '{}' [{}] greater than configured max length ({}).", path, index, maxLength);
                                }
                            }
                        } else { // single property value
                            if (checkLength(property.getLength(), maxLength)) {
                                jobManager.addJob(scanJobTopic(propertyType), properties(path, userId));
                            } else {
                                logger.warn("Length of property '{}' greater than configured max length ({}).", path, maxLength);
                            }
                        }
                    }
                }
            } catch (Exception e) {
                logger.error(e.getMessage());
            }
        }
    }

}
