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


import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

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.ValueMap;
import org.apache.sling.event.impl.jobs.config.JobManagerConfiguration;
import org.apache.sling.event.impl.jobs.config.QueueConfigurationManager.QueueInfo;
import org.apache.sling.event.impl.jobs.config.TopologyCapabilities;
import org.apache.sling.event.impl.support.ResourceHelper;
import org.apache.sling.event.jobs.Job;
import org.apache.sling.event.jobs.Queue;
import org.apache.sling.event.jobs.consumer.JobExecutor;


/**
 * This object adds actions to a {@link JobImpl}.
 */
public class JobHandler {

    private final JobImpl job;

    public volatile long started = -1;

    private volatile boolean isStopped = false;

    private final JobManagerConfiguration configuration;

    private final JobExecutor consumer;

    public JobHandler(final JobImpl job,
            final JobExecutor consumer,
            final JobManagerConfiguration configuration) {
        this.job = job;
        this.consumer = consumer;
        this.configuration = configuration;
    }

    public JobImpl getJob() {
        return this.job;
    }

    public JobExecutor getConsumer() {
        return this.consumer;
    }

    public boolean startProcessing(final Queue queue) {
        this.isStopped = false;
        return this.persistJobProperties(this.job.prepare(queue));
    }

    /**
     * Reschedule the job
     * Update the retry count and remove the started time.
     * @return <code>true</code> if rescheduling was successful, <code>false</code> otherwise.
     */
    public boolean reschedule() {
        final ResourceResolver resolver = this.configuration.createResourceResolver();
        try {
            final Resource jobResource = resolver.getResource(job.getResourcePath());
            if ( jobResource != null ) {
                final ModifiableValueMap mvm = jobResource.adaptTo(ModifiableValueMap.class);
                mvm.put(Job.PROPERTY_JOB_RETRY_COUNT, job.getProperty(Job.PROPERTY_JOB_RETRY_COUNT, Integer.class));
                if ( job.getProperty(Job.PROPERTY_RESULT_MESSAGE) != null ) {
                    mvm.put(Job.PROPERTY_RESULT_MESSAGE, job.getProperty(Job.PROPERTY_RESULT_MESSAGE));
                }
                mvm.remove(Job.PROPERTY_JOB_STARTED_TIME);
                mvm.put(JobImpl.PROPERTY_JOB_QUEUED, Calendar.getInstance());
                try {
                    resolver.commit();
                    return true;
                } catch ( final PersistenceException pe ) {
                    this.configuration.getMainLogger().debug("Unable to update reschedule properties for job " + job.getId(), pe);
                }
            }
        } finally {
            resolver.close();
        }

        return false;
    }

    /**
     * Finish a job.
     * @param state The state of the processing
     * @param keepJobInHistory whether to keep the job in the job history.
     * @param duration the duration of the processing.
     */
    public void finished(final Job.JobState state,
                          final boolean keepJobInHistory,
                          final Long duration) {
        final boolean isSuccess = (state == Job.JobState.SUCCEEDED);
        final ResourceResolver resolver = this.configuration.createResourceResolver();
        try {
            final Resource jobResource = resolver.getResource(job.getResourcePath());
            if ( jobResource != null ) {
                try {
                    String newPath = null;
                    if ( keepJobInHistory ) {
                        final ValueMap vm = ResourceHelper.getValueMap(jobResource);
                        newPath = this.configuration.getStoragePath(job.getTopic(), job.getId(), isSuccess);
                        final Map<String, Object> props = new HashMap<>(vm);
                        props.put(JobImpl.PROPERTY_FINISHED_STATE, state.name());
                        if ( isSuccess ) {
                            // we set the finish date to start date + duration
                            final Date finishDate = new Date();
                            finishDate.setTime(job.getProcessingStarted().getTime().getTime() + duration);
                            final Calendar finishCal = Calendar.getInstance();
                            finishCal.setTime(finishDate);
                            props.put(JobImpl.PROPERTY_FINISHED_DATE, finishCal);
                        } else {
                            // current time is good enough
                            props.put(JobImpl.PROPERTY_FINISHED_DATE, Calendar.getInstance());
                        }
                        if ( job.getProperty(Job.PROPERTY_RESULT_MESSAGE) != null ) {
                            props.put(Job.PROPERTY_RESULT_MESSAGE, job.getProperty(Job.PROPERTY_RESULT_MESSAGE));
                        }
                        ResourceHelper.getOrCreateResource(resolver, newPath, props);
                    }
                    resolver.delete(jobResource);
                    resolver.commit();

                    if ( keepJobInHistory && configuration.getMainLogger().isDebugEnabled() ) {
                        if ( isSuccess ) {
                            configuration.getMainLogger().debug("Kept successful job {} at {}", Utility.toString(job), newPath);
                        } else {
                            configuration.getMainLogger().debug("Moved cancelled job {} to {}", Utility.toString(job), newPath);
                        }
                    }
                } catch ( final PersistenceException pe ) {
                    this.configuration.getMainLogger().warn("Unable to finish job " + job.getId(), pe);
                } catch (final InstantiationException ie) {
                    // something happened with the resource in the meantime
                    this.configuration.getMainLogger().debug("Unable to instantiate job", ie);
                }
            }
        } finally {
            resolver.close();
        }
    }

    /**
     * Reassign to a new instance.
     */
    public void reassign() {
        final QueueInfo queueInfo = this.configuration.getQueueConfigurationManager().getQueueInfo(job.getTopic());
        // Sanity check if queue configuration has changed
        final TopologyCapabilities caps = this.configuration.getTopologyCapabilities();
        final String targetId = (caps == null ? null : caps.detectTarget(job.getTopic(), job.getProperties(), queueInfo));

        final ResourceResolver resolver = this.configuration.createResourceResolver();
        try {
            final Resource jobResource = resolver.getResource(job.getResourcePath());
            if ( jobResource != null ) {
                try {
                    final ValueMap vm = ResourceHelper.getValueMap(jobResource);
                    final String newPath = this.configuration.getUniquePath(targetId, job.getTopic(), job.getId(), job.getProperties());

                    final Map<String, Object> props = new HashMap<>(vm);
                    props.remove(Job.PROPERTY_JOB_QUEUE_NAME);
                    if ( targetId == null ) {
                        props.remove(Job.PROPERTY_JOB_TARGET_INSTANCE);
                    } else {
                        props.put(Job.PROPERTY_JOB_TARGET_INSTANCE, targetId);
                    }
                    props.remove(Job.PROPERTY_JOB_STARTED_TIME);

                    try {
                        ResourceHelper.getOrCreateResource(resolver, newPath, props);
                        resolver.delete(jobResource);
                        resolver.commit();
                    } catch ( final PersistenceException pe ) {
                        this.configuration.getMainLogger().warn("Unable to reassign job " + job.getId(), pe);
                    }
                } catch (final InstantiationException ie) {
                    // something happened with the resource in the meantime
                    this.configuration.getMainLogger().debug("Unable to instantiate job", ie);
                }
            }
        } finally {
            resolver.close();
        }
    }

    /**
     * Update the property of a job in the resource tree
     * @param propNames the property names to update
     * @return {@code true} if the update was successful.
     */
    public boolean persistJobProperties(final String... propNames) {
        if ( propNames != null ) {
            final ResourceResolver resolver = this.configuration.createResourceResolver();
            try {
                final Resource jobResource = resolver.getResource(job.getResourcePath());
                if ( jobResource != null ) {
                    final ModifiableValueMap mvm = jobResource.adaptTo(ModifiableValueMap.class);
                    for(final String propName : propNames) {
                        final Object val = job.getProperty(propName);
                        if ( val != null ) {
                            if ( val.getClass().isEnum() ) {
                                mvm.put(propName, val.toString());
                            } else {
                                mvm.put(propName, val);
                            }
                        } else {
                            mvm.remove(propName);
                        }
                    }
                    resolver.commit();

                    return true;
                } else {
                    this.configuration.getMainLogger().debug("No job resource found at {}", job.getResourcePath());
                }
            } catch ( final PersistenceException ignore ) {
                this.configuration.getMainLogger().debug("Unable to persist properties", ignore);
            } finally {
                resolver.close();
            }
            return false;
        }
        return true;
    }

    public boolean isStopped() {
        return this.isStopped;
    }

    public void stop() {
        this.isStopped = true;
    }

    public void addToRetryList() {
        this.configuration.addJobToRetryList(this.job);

    }

    public boolean removeFromRetryList() {
        return this.configuration.removeJobFromRetryList(this.job);
    }

    @Override
    public int hashCode() {
        return this.job.getId().hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if ( ! (obj instanceof JobHandler) ) {
            return false;
        }
        return this.job.getId().equals(((JobHandler)obj).job.getId());
    }

    @Override
    public String toString() {
        return "JobHandler(" + this.job.getId() + ")";
    }
}