/*
 * 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.scheduling;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.sling.api.resource.ModifiableValueMap;
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.observation.ExternalResourceChangeListener;
import org.apache.sling.api.resource.observation.ResourceChange;
import org.apache.sling.api.resource.observation.ResourceChangeListener;
import org.apache.sling.commons.scheduler.JobContext;
import org.apache.sling.commons.scheduler.ScheduleOptions;
import org.apache.sling.commons.scheduler.Scheduler;
import org.apache.sling.event.impl.jobs.JobManagerImpl;
import org.apache.sling.event.impl.jobs.Utility;
import org.apache.sling.event.impl.jobs.config.ConfigurationChangeListener;
import org.apache.sling.event.impl.jobs.config.JobManagerConfiguration;
import org.apache.sling.event.impl.jobs.config.TopologyCapabilities;
import org.apache.sling.event.impl.support.ResourceHelper;
import org.apache.sling.event.impl.support.ScheduleInfoImpl;
import org.apache.sling.event.jobs.JobBuilder;
import org.apache.sling.event.jobs.ScheduleInfo;
import org.apache.sling.event.jobs.ScheduleInfo.ScheduleType;
import org.apache.sling.event.jobs.ScheduledJobInfo;
import org.osgi.service.event.Event;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * The scheduler for managing scheduled jobs.
 *
 * This is not a component by itself, it's directly created from the job manager.
 * The job manager is also registering itself as an event handler and forwards
 * the events to this service.
 */
public class JobSchedulerImpl
    implements ConfigurationChangeListener,
               ResourceChangeListener, ExternalResourceChangeListener,
               org.apache.sling.commons.scheduler.Job {

    private static final String PROPERTY_READ_JOB = "properties";

    private static final String PROPERTY_SCHEDULE_INDEX = "index";

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

    /** Is this active? */
    private final AtomicBoolean active = new AtomicBoolean(false);

    /** Central job handling configuration. */
    private final JobManagerConfiguration configuration;

    /** Scheduler service. */
    private final Scheduler scheduler;

    /** Job manager. */
    private final JobManagerImpl jobManager;

    /** Scheduled job handler. */
    private final ScheduledJobHandler scheduledJobHandler;

    /** All scheduled jobs, by scheduler name */
    private final Map<String, ScheduledJobInfoImpl> scheduledJobs = new HashMap<>();

    /**
     * Create the scheduler
     * @param configuration Central job manager configuration
     * @param scheduler The scheduler service
     * @param jobManager The job manager
     */
    public JobSchedulerImpl(final JobManagerConfiguration configuration,
            final Scheduler scheduler,
            final JobManagerImpl jobManager) {
        this.configuration = configuration;
        this.scheduler = scheduler;
        this.jobManager = jobManager;

        this.configuration.addListener(this);

        this.scheduledJobHandler = new ScheduledJobHandler(configuration, this);
    }

    /**
     * Deactivate this component.
     */
    public void deactivate() {
        this.configuration.removeListener(this);

        this.scheduledJobHandler.deactivate();

        if ( this.active.compareAndSet(true, false) ) {
            this.stopScheduling();
        }
        synchronized ( this.scheduledJobs ) {
            this.scheduledJobs.clear();
        }
    }

    /**
     * @see org.apache.sling.event.impl.jobs.config.ConfigurationChangeListener#configurationChanged(boolean)
     */
    @Override
    public void configurationChanged(final boolean processingActive) {
        // scheduling is only active if
        // - processing is active and
        // - configuration is still available and active
        // - and current instance is leader
        final boolean schedulingActive;
        if ( processingActive ) {
            final TopologyCapabilities caps = this.configuration.getTopologyCapabilities();
            if ( caps != null && caps.isActive() ) {
                schedulingActive = caps.isLeader();
            } else {
                schedulingActive = false;
            }
        } else {
            schedulingActive = false;
        }

        // switch activation based on current state and new state
        if ( schedulingActive ) {
            // activate if inactive
            if ( this.active.compareAndSet(false, true) ) {
                this.startScheduling();
            }
        } else {
            // deactivate if active
            if ( this.active.compareAndSet(true, false) ) {
                this.stopScheduling();
            }
        }
    }

    /**
     * Start all scheduled jobs
     */
    private void startScheduling() {
        synchronized ( this.scheduledJobs ) {
            for(final ScheduledJobInfo info : this.scheduledJobs.values()) {
                this.startScheduledJob(((ScheduledJobInfoImpl)info));
            }
        }
    }

    /**
     * Stop all scheduled jobs.
     */
    private void stopScheduling() {
        synchronized ( this.scheduledJobs ) {
            for(final ScheduledJobInfo info : this.scheduledJobs.values()) {
                this.stopScheduledJob((ScheduledJobInfoImpl)info);
            }
        }
    }

    /**
     * Add a scheduled job
     */
    public void scheduleJob(final ScheduledJobInfoImpl info) {
        synchronized ( this.scheduledJobs ) {
            this.scheduledJobs.put(info.getName(), info);
            this.startScheduledJob(info);
        }
    }

    /**
     * Unschedule a scheduled job
     */
    public void unscheduleJob(final ScheduledJobInfoImpl info) {
        synchronized ( this.scheduledJobs ) {
            if ( this.scheduledJobs.remove(info.getName()) != null ) {
                this.stopScheduledJob(info);
            }
        }
    }

    /**
     * Remove a scheduled job
     */
    public void removeJob(final ScheduledJobInfoImpl info) {
        this.unscheduleJob(info);
        this.scheduledJobHandler.remove(info);
    }

    /**
     * Start a scheduled job
     * @param info The scheduling info
     */
    private void startScheduledJob(final ScheduledJobInfoImpl info) {
        if ( this.active.get() ) {
            if ( !info.isSuspended() ) {
                this.configuration.getAuditLogger().debug("SCHEDULED OK name={}, topic={}, properties={} : {}",
                        new Object[] {info.getName(),
                                      info.getJobTopic(),
                                      info.getJobProperties()},
                                      info.getSchedules());
                int index = 0;
                for(final ScheduleInfo si : info.getSchedules()) {
                    final String name = info.getSchedulerJobId() + "-" + String.valueOf(index);
                    ScheduleOptions options = null;
                    switch ( si.getType() ) {
                        case DAILY:
                        case WEEKLY:
                        case HOURLY:
                        case MONTHLY:
                        case YEARLY:
                        case CRON:
                            options = this.scheduler.EXPR(((ScheduleInfoImpl)si).getCronExpression());

                            break;
                        case DATE:
                            options = this.scheduler.AT(((ScheduleInfoImpl)si).getNextScheduledExecution());
                            break;
                    }
                    // Create configuration for scheduled job
                    final Map<String, Serializable> config = new HashMap<>();
                    config.put(PROPERTY_READ_JOB, info);
                    config.put(PROPERTY_SCHEDULE_INDEX, index);
                    this.scheduler.schedule(this, options.name(name).config(config).canRunConcurrently(false));
                    index++;
                }
            } else {
                this.configuration.getAuditLogger().debug("SCHEDULED SUSPENDED name={}, topic={}, properties={} : {}",
                        new Object[] {info.getName(),
                                      info.getJobTopic(),
                                      info.getJobProperties(),
                                      info.getSchedules()});
            }
        }
    }

    /**
     * Stop a scheduled job
     * @param info The scheduling info
     */
    private void stopScheduledJob(final ScheduledJobInfoImpl info) {
        final Scheduler localScheduler = this.scheduler;
        if ( localScheduler != null ) {
            this.configuration.getAuditLogger().debug("SCHEDULED STOP name={}, topic={}, properties={} : {}",
                    new Object[] {info.getName(),
                                  info.getJobTopic(),
                                  info.getJobProperties(),
                                  info.getSchedules()});
            for(int index = 0; index<info.getSchedules().size(); index++) {
                final String name = info.getSchedulerJobId() + "-" + String.valueOf(index);
                localScheduler.unschedule(name);
            }
        }
    }

    /**
     * @see org.apache.sling.commons.scheduler.Job#execute(org.apache.sling.commons.scheduler.JobContext)
     */
    @Override
    public void execute(final JobContext context) {
        if ( !active.get() ) {
            // not active anymore, simply return
            return;
        }
        final ScheduledJobInfoImpl info = (ScheduledJobInfoImpl) context.getConfiguration().get(PROPERTY_READ_JOB);

        if ( info.isSuspended() ) {
            return;
        }

        this.jobManager.addJob(info.getJobTopic(), info.getJobProperties());
        final int index = (Integer)context.getConfiguration().get(PROPERTY_SCHEDULE_INDEX);
        final Iterator<ScheduleInfo> iter = info.getSchedules().iterator();
        ScheduleInfo si = iter.next();
        for(int i=0; i<index; i++) {
            si = iter.next();
        }
        // if scheduled once (DATE), remove from schedule
        if ( si.getType() == ScheduleType.DATE ) {
            if ( index == 0 && info.getSchedules().size() == 1 ) {
                // remove
                this.scheduledJobHandler.remove(info);
            } else {
                // update schedule list
                final List<ScheduleInfo> infos = new ArrayList<>();
                for(final ScheduleInfo i : info.getSchedules() ) {
                    if ( i != si ) { // no need to use equals
                        infos.add(i);
                    }
                }
                info.update(infos);
                this.scheduledJobHandler.updateSchedule(info.getName(), infos);
            }
        }
    }

    /**
     * @see org.osgi.service.event.EventHandler#handleEvent(org.osgi.service.event.Event)
     */
    public void handleEvent(final Event event) {
        if ( ResourceHelper.BUNDLE_EVENT_STARTED.equals(event.getTopic())
             || ResourceHelper.BUNDLE_EVENT_UPDATED.equals(event.getTopic()) ) {
            this.scheduledJobHandler.bundleEvent();
        }
    }

    /**
     * Helper method which just logs the exception in debug mode.
     * @param e
     */
    private void ignoreException(final Exception e) {
        if ( this.logger.isDebugEnabled() ) {
            this.logger.debug("Ignored exception " + e.getMessage(), e);
        }
    }

    /**
     * Create a schedule builder for a currently scheduled job
     */
    public JobBuilder.ScheduleBuilder createJobBuilder(final ScheduledJobInfoImpl info) {
        final JobBuilder.ScheduleBuilder sb = new JobScheduleBuilderImpl(info.getJobTopic(),
                info.getJobProperties(), info.getName(), this);
        return (info.isSuspended() ? sb.suspend() : sb);
    }

    private enum Operation {
        LESS,
        LESS_OR_EQUALS,
        EQUALS,
        GREATER_OR_EQUALS,
        GREATER
    }

    /**
     * Check if the job matches the template
     */
    private boolean match(final ScheduledJobInfoImpl job, final Map<String, Object> template) {
        if ( template != null ) {
            for(final Map.Entry<String, Object> current : template.entrySet()) {
                final String key = current.getKey();
                final char firstChar = key.length() > 0 ? key.charAt(0) : 0;
                final String propName;
                final Operation op;
                if ( firstChar == '=' ) {
                    propName = key.substring(1);
                    op  = Operation.EQUALS;
                } else if ( firstChar == '<' ) {
                    final char secondChar = key.length() > 1 ? key.charAt(1) : 0;
                    if ( secondChar == '=' ) {
                        op = Operation.LESS_OR_EQUALS;
                        propName = key.substring(2);
                    } else {
                        op = Operation.LESS;
                        propName = key.substring(1);
                    }
                } else if ( firstChar == '>' ) {
                    final char secondChar = key.length() > 1 ? key.charAt(1) : 0;
                    if ( secondChar == '=' ) {
                        op = Operation.GREATER_OR_EQUALS;
                        propName = key.substring(2);
                    } else {
                        op = Operation.GREATER;
                        propName = key.substring(1);
                    }
                } else {
                    propName = key;
                    op  = Operation.EQUALS;
                }
                final Object value = current.getValue();

                if ( op == Operation.EQUALS ) {
                    if ( !value.equals(job.getJobProperties().get(propName)) ) {
                        return false;
                    }
                } else {
                    if ( value instanceof Comparable ) {
                        @SuppressWarnings({ "unchecked", "rawtypes" })
                        final int result = ((Comparable)value).compareTo(job.getJobProperties().get(propName));
                        if ( op == Operation.LESS && result > -1 ) {
                            return false;
                        } else if ( op == Operation.LESS_OR_EQUALS && result > 0 ) {
                            return false;
                        } else if ( op == Operation.GREATER_OR_EQUALS && result < 0 ) {
                            return false;
                        } else if ( op == Operation.GREATER && result < 1 ) {
                            return false;
                        }
                    } else {
                        // if the value is not comparable we simply don't match
                        return false;
                    }
                }
            }
        }
        return true;
    }

    /**
     * Get all scheduled jobs
     */
    public Collection<ScheduledJobInfo> getScheduledJobs(final String topic,
            final long limit,
            final Map<String, Object>... templates) {
        final List<ScheduledJobInfo> jobs = new ArrayList<>();
        long count = 0;
        synchronized ( this.scheduledJobs ) {
            for(final ScheduledJobInfoImpl job : this.scheduledJobs.values() ) {
                boolean add = true;
                if ( topic != null && !topic.equals(job.getJobTopic()) ) {
                    add = false;
                }
                if ( add && templates != null && templates.length != 0 ) {
                    add = false;
                    for (Map<String,Object> template : templates) {
                        add = this.match(job, template);
                        if ( add ) {
                            break;
                        }
                    }
                }
                if ( add ) {
                    jobs.add(job);
                    count++;
                    if ( limit > 0 && count == limit ) {
                        break;
                    }
                }
            }
        }
        return jobs;
    }

    /**
     * Change the suspended flag for a scheduled job
     * @param info The schedule info
     * @param flag The corresponding flag
     */
    public void setSuspended(final ScheduledJobInfoImpl info, final boolean flag) {
        final ResourceResolver resolver = configuration.createResourceResolver();
        try {
            final StringBuilder sb = new StringBuilder(this.configuration.getScheduledJobsPath(true));
            sb.append(ResourceHelper.filterName(info.getName()));
            final String path = sb.toString();

            final Resource eventResource = resolver.getResource(path);
            if ( eventResource != null ) {
                final ModifiableValueMap mvm = eventResource.adaptTo(ModifiableValueMap.class);
                if ( flag ) {
                    mvm.put(ResourceHelper.PROPERTY_SCHEDULE_SUSPENDED, Boolean.TRUE);
                } else {
                    mvm.remove(ResourceHelper.PROPERTY_SCHEDULE_SUSPENDED);
                }
                resolver.commit();
            }
            if ( flag ) {
                this.stopScheduledJob(info);
            } else {
                this.startScheduledJob(info);
            }
        } catch (final PersistenceException pe) {
            // we ignore the exception if removing fails
            ignoreException(pe);
        } finally {
            resolver.close();
        }
    }

    /**
     * Add a scheduled job
     * @param topic The job topic
     * @param properties The job properties
     * @param scheduleName The schedule name
     * @param isSuspended Whether it is suspended
     * @param scheduleInfos The scheduling information
     * @param errors Optional list to contain potential errors
     * @return A new job info or {@code null}
     */
    public ScheduledJobInfo addScheduledJob(final String topic,
            final Map<String, Object> properties,
            final String scheduleName,
            final boolean isSuspended,
            final List<ScheduleInfoImpl> scheduleInfos,
            final List<String> errors) {
        final List<String> msgs = new ArrayList<>();
        if ( scheduleName == null || scheduleName.length() == 0 ) {
            msgs.add("Schedule name not specified");
        }
        final String errorMessage = Utility.checkJob(topic, properties);
        if ( errorMessage != null ) {
            msgs.add(errorMessage);
        }
        if ( scheduleInfos.size() == 0 ) {
            msgs.add("No schedule defined for " + scheduleName);
        }
        for(final ScheduleInfoImpl info : scheduleInfos) {
            info.check(msgs);
        }
        if ( msgs.size() == 0 ) {
            try {
                final ScheduledJobInfo info = this.scheduledJobHandler.addOrUpdateJob(topic, properties, scheduleName, isSuspended, scheduleInfos);
                if ( info != null ) {
                    return info;
                }
                msgs.add("Unable to persist scheduled job.");
            } catch ( final PersistenceException pe) {
                msgs.add("Unable to persist scheduled job: " + scheduleName);
                logger.warn("Unable to persist scheduled job", pe);
            }
        } else {
            for(final String msg : msgs) {
                logger.warn(msg);
            }
        }
        if ( errors != null ) {
            errors.addAll(msgs);
        }
        return null;
    }

    public void maintenance() {
        this.scheduledJobHandler.maintenance();
    }

    /**
     * @see org.apache.sling.api.resource.observation.ResourceChangeListener#onChange(java.util.List)
     */
    @Override
    public void onChange(List<ResourceChange> changes) {
        for(final ResourceChange change : changes ) {
            if ( change.getPath() != null && change.getPath().startsWith(this.configuration.getScheduledJobsPath(true)) ) {
                if ( change.getType() == ResourceChange.ChangeType.REMOVED ) {
                    // removal
                    logger.debug("Remove scheduled job {}", change.getPath());
                    this.scheduledJobHandler.handleRemove(change.getPath());
                } else {
                    // add or update
                    logger.debug("Add or update scheduled job {}, event {}", change.getPath(), change.getType());
                    this.scheduledJobHandler.handleAddUpdate(change.getPath());
                }
            }
        }
    }
}
