/*
 * 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.event.impl.jobs.tasks;

import org.apache.sling.api.resource.PersistenceException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.event.impl.jobs.JobImpl;
import org.apache.sling.event.impl.jobs.config.JobManagerConfiguration;
import org.apache.sling.event.jobs.Job;
import org.apache.sling.event.jobs.consumer.JobExecutionContext;
import org.apache.sling.event.jobs.consumer.JobExecutionResult;
import org.apache.sling.event.jobs.consumer.JobExecutor;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;

/**
 * Task to clean up the history,
 * A clean up task can be configured with three properties:
 * - age : only jobs older than this amount of minutes are removed (default is two days)
 * - topic : only jobs with this topic are removed (default is no topic, meaning all jobs are removed)
 *           The value should either be a string or an array of string
 * - state : only jobs in this state are removed (default is no state, meaning all jobs are removed)
 *           The value should either be a string or an array of string. Allowed values are:
 *           SUCCEEDED, STOPPED, GIVEN_UP, ERROR, DROPPED
 */
@Component(service = JobExecutor.class,
    property = {
        JobExecutor.PROPERTY_TOPICS + "=org/apache/sling/event/impl/jobs/tasks/HistoryCleanUpTask",
        Constants.SERVICE_VENDOR + "=The Apache Software Foundation"
})
public class HistoryCleanUpTask implements JobExecutor {

    private static final String PROPERTY_AGE = "age";

    private static final String PROPERTY_TOPIC = "topic";

    private static final String PROPERTY_STATE = "state";

    private static final int DEFAULT_AGE = 60 * 24 * 2; // older than two days

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Reference
    private JobManagerConfiguration configuration;

    @Override
    public JobExecutionResult process(final Job job, final JobExecutionContext context) {
        int age = job.getProperty(PROPERTY_AGE, DEFAULT_AGE);
        if ( age < 1 ) {
            age = DEFAULT_AGE;
        }
        final Calendar removeDate = Calendar.getInstance();
        removeDate.add(Calendar.MINUTE, -age);

        final String[] topics = job.getProperty(PROPERTY_TOPIC, String[].class);
        final String[] states = job.getProperty(PROPERTY_STATE, String[].class);
        final String logTopics = (topics == null ? "ALL" : Arrays.toString(topics));
        final String logStates = (states == null ? "ALL" : Arrays.toString(states));
        context.log("Cleaning up job history. Removing all jobs older than {0}, with topics {1} and states {2}",
                removeDate, logTopics, logStates);

        final List<String> stateList;
        if ( states != null ) {
            stateList = new ArrayList<>();
            for(final String s : states) {
                stateList.add(s);
            }
        } else {
            stateList = null;
        }
        final ResourceResolver resolver = this.configuration.createResourceResolver();
        try {
            if ( stateList == null || stateList.contains(Job.JobState.SUCCEEDED.name()) ) {
                this.cleanup(removeDate, resolver, context, configuration.getStoredSuccessfulJobsPath(), topics, null);
            }
            if ( stateList == null || stateList.contains(Job.JobState.DROPPED.name())
                 || stateList.contains(Job.JobState.ERROR.name())
                 || stateList.contains(Job.JobState.GIVEN_UP.name())
                 || stateList.contains(Job.JobState.STOPPED.name())) {
                this.cleanup(removeDate, resolver, context, configuration.getStoredCancelledJobsPath(), topics, stateList);
            }

        } catch (final PersistenceException pe) {
            // in the case of an error, we just log this as a warning
            this.logger.warn("Exception during job resource tree cleanup.", pe);
        } finally {
            resolver.close();
        }
        return context.result().succeeded();
    }

    static void cleanup(final Calendar removeDate,
            final ResourceResolver resolver,
            final JobExecutionContext context,
            final String basePath,
            final String[] topics,
            final List<String> stateList)
    throws PersistenceException {
        final Resource baseResource = resolver.getResource(basePath);
        // sanity check - should never be null
        if ( baseResource != null ) {
            final Iterator<Resource> topicIter = baseResource.listChildren();
            while ( !context.isStopped() && topicIter.hasNext() ) {
                final Resource topicResource = topicIter.next();

                // check topic
                boolean found = topics == null;
                int index = 0;
                while ( !found && index < topics.length ) {
                    if ( topicResource.getName().equals(topics[index]) ) {
                        found = true;
                    }
                    index++;
                }
                if ( !found ) {
                    continue;
                }

                final int removeYear = removeDate.get(Calendar.YEAR);
                final int removeMonth = removeDate.get(Calendar.MONTH) + 1;
                final int removeDay = removeDate.get(Calendar.DAY_OF_MONTH);
                final int removeHour = removeDate.get(Calendar.HOUR_OF_DAY);
                final int removeMinute = removeDate.get(Calendar.MINUTE);

                // start with years
                final Iterator<Resource> yearIter = topicResource.listChildren();
                while ( !context.isStopped() && yearIter.hasNext() ) {
                    final Resource yearResource = yearIter.next();
                    final int year = Integer.valueOf(yearResource.getName());
                    if ( year > removeYear ) {
                        continue;
                    }
                    final boolean oldYear = year < removeYear;

                    // months
                    final Iterator<Resource> monthIter = yearResource.listChildren();
                    while ( !context.isStopped() && monthIter.hasNext() ) {
                        final Resource monthResource = monthIter.next();
                        final int month = Integer.valueOf(monthResource.getName());
                        if ( !oldYear && month > removeMonth) {
                            continue;
                        }
                        final boolean oldMonth = oldYear || month < removeMonth;

                        // days
                        final Iterator<Resource> dayIter = monthResource.listChildren();
                        while ( !context.isStopped() && dayIter.hasNext() ) {
                            final Resource dayResource = dayIter.next();
                            final int day = Integer.valueOf(dayResource.getName());
                            if ( !oldMonth && day > removeDay) {
                                continue;
                            }
                            final boolean oldDay = oldMonth || day < removeDay;

                            // hours
                            final Iterator<Resource> hourIter = dayResource.listChildren();
                            while ( !context.isStopped() && hourIter.hasNext() ) {
                                final Resource hourResource = hourIter.next();
                                final int hour = Integer.valueOf(hourResource.getName());
                                if ( !oldDay && hour > removeHour) {
                                    continue;
                                }
                                final boolean oldHour = oldDay || hour < removeHour;

                                // minutes
                                final Iterator<Resource> minuteIter = hourResource.listChildren();
                                while ( !context.isStopped() && minuteIter.hasNext() ) {
                                    final Resource minuteResource = minuteIter.next();

                                    // check if we can delete the minute
                                    final int minute = Integer.valueOf(minuteResource.getName());
                                    final boolean oldMinute = oldHour || minute <= removeMinute;

                                    if ( oldMinute ) {
                                        final Iterator<Resource> jobIter = minuteResource.listChildren();
                                        while ( !context.isStopped() && jobIter.hasNext() ) {
                                            final Resource jobResource = jobIter.next();
                                            boolean remove = stateList == null;
                                            if ( !remove ) {
                                                final ValueMap vm = ResourceUtil.getValueMap(jobResource);
                                                final String state = vm.get(JobImpl.PROPERTY_FINISHED_STATE, String.class);
                                                if ( state != null && stateList.contains(state) ) {
                                                    remove = true;
                                                }
                                            }
                                            if ( remove ) {
                                                resolver.delete(jobResource);
                                                resolver.commit();
                                            }
                                        }
                                        // check if we can delete the minute
                                        if ( !context.isStopped() && !minuteResource.listChildren().hasNext()) {
                                            resolver.delete(minuteResource);
                                            resolver.commit();
                                        }
                                    }
                                }

                                // check if we can delete the hour
                                if ( !context.isStopped() && oldHour && !hourResource.listChildren().hasNext()) {
                                    resolver.delete(hourResource);
                                    resolver.commit();
                                }
                            }
                            // check if we can delete the day
                            if ( !context.isStopped() && oldDay && !dayResource.listChildren().hasNext()) {
                                resolver.delete(dayResource);
                                resolver.commit();
                            }
                        }

                        // check if we can delete the month
                        if ( !context.isStopped() && oldMonth && !monthResource.listChildren().hasNext() ) {
                            resolver.delete(monthResource);
                            resolver.commit();
                        }
                    }

                    // check if we can delete the year
                    if ( !context.isStopped() && oldYear && !yearResource.listChildren().hasNext() ) {
                        resolver.delete(yearResource);
                        resolver.commit();
                    }
                }
            }
        }
    }
}
