/*
 * 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.openejb.resource.quartz;

import org.apache.openejb.loader.SystemInstance;
import org.apache.openejb.quartz.Job;
import org.apache.openejb.quartz.JobDataMap;
import org.apache.openejb.quartz.JobExecutionContext;
import org.apache.openejb.quartz.JobExecutionException;
import org.apache.openejb.quartz.Scheduler;
import org.apache.openejb.quartz.SchedulerException;
import org.apache.openejb.quartz.impl.StdSchedulerFactory;
import org.apache.openejb.quartz.listeners.SchedulerListenerSupport;
import org.apache.openejb.util.JavaSecurityManagers;
import org.apache.openejb.util.LogCategory;
import org.apache.openejb.util.Logger;

import javax.resource.ResourceException;
import javax.resource.spi.ActivationSpec;
import javax.resource.spi.BootstrapContext;
import javax.resource.spi.ResourceAdapter;
import javax.resource.spi.ResourceAdapterInternalException;
import javax.resource.spi.endpoint.MessageEndpoint;
import javax.resource.spi.endpoint.MessageEndpointFactory;
import javax.transaction.xa.XAResource;
import java.lang.reflect.Method;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @version $Rev$ $Date$
 */
public class QuartzResourceAdapter implements ResourceAdapter {

    public static final String OPENEJB_QUARTZ_TIMEOUT = "openejb.quartz.timeout";

    //Start and stop may be called from different threads so use atomics
    private final AtomicReference<Throwable> ex = new AtomicReference<>();
    private final AtomicReference<Scheduler> scheduler = new AtomicReference<>();
    private final AtomicReference<BootstrapContext> bootstrapContext = new AtomicReference<>();
    private final AtomicReference<Thread> startThread = new AtomicReference<>();

    @Override
    public void start(final BootstrapContext bootstrapContext) throws ResourceAdapterInternalException {

        if (null != this.bootstrapContext.getAndSet(bootstrapContext)) {
            Logger.getInstance(LogCategory.OPENEJB, "org.apache.openejb.util.resources").warning("QuartzResourceAdapter is already starting");
            return;
        }

        final CountDownLatch signal = new CountDownLatch(1);
        long timeout = SystemInstance.get().getOptions().get(QuartzResourceAdapter.OPENEJB_QUARTZ_TIMEOUT, 10000L);

        if (timeout < 1000L) {
            timeout = 1000L;
        }

        if (timeout > 60000L) {
            timeout = 60000L;
        }

        //Allow org.apache.openejb.quartz.InterruptableJob implementors to be interrupted on shutdown
        JavaSecurityManagers.setSystemProperty(StdSchedulerFactory.PROP_SCHED_INTERRUPT_JOBS_ON_SHUTDOWN
            , JavaSecurityManagers.getSystemProperty(StdSchedulerFactory.PROP_SCHED_INTERRUPT_JOBS_ON_SHUTDOWN, "true"));
        JavaSecurityManagers.setSystemProperty(StdSchedulerFactory.PROP_SCHED_INTERRUPT_JOBS_ON_SHUTDOWN_WITH_WAIT
            , JavaSecurityManagers.getSystemProperty(StdSchedulerFactory.PROP_SCHED_INTERRUPT_JOBS_ON_SHUTDOWN_WITH_WAIT, "true"));

        //Let the user enable this if they really want it
        JavaSecurityManagers.setSystemProperty("org.terracotta.quartz.skipUpdateCheck"
            , JavaSecurityManagers.getSystemProperty("org.terracotta.quartz.skipUpdateCheck", "true"));

        startThread.set(new Thread("Quartz Scheduler Start") {

            @Override
            public void run() {

                try {
                    QuartzResourceAdapter.this.scheduler.set(StdSchedulerFactory.getDefaultScheduler());
                } catch (final Exception e) {
                    QuartzResourceAdapter.this.ex.set(e);
                    return;
                }

                try {
                    QuartzResourceAdapter.this.scheduler.get().getListenerManager().addSchedulerListener(new SchedulerListenerSupport() {
                        @Override
                        public void schedulerStarted() {
                            signal.countDown();
                        }
                    });

                    QuartzResourceAdapter.this.scheduler.get().start();

                } catch (final Throwable e) {
                    QuartzResourceAdapter.this.ex.set(e);
                    signal.countDown();
                }
            }
        });

        startThread.get().setDaemon(true);
        startThread.get().start();

        boolean started = false;
        try {
            started = signal.await(timeout, TimeUnit.MILLISECONDS);
        } catch (final InterruptedException e) {
            //Ignore
        }

        final Throwable exception = ex.get();
        if (null != exception) {
            final String err = "Error creating Quartz Scheduler";
            Logger.getInstance(LogCategory.OPENEJB, "org.apache.openejb.util.resources").error(err, exception);
            throw new ResourceAdapterInternalException(err, exception);
        }

        if (started) {
            Logger.getInstance(LogCategory.OPENEJB, "org.apache.openejb.util.resources").info("Started Quartz Scheduler");
        } else {
            Logger.getInstance(LogCategory.OPENEJB, "org.apache.openejb.util.resources").warning("Failed to start Quartz Scheduler within defined timeout, status unknown");
        }
    }

    public Scheduler getScheduler() {
        return scheduler.get();
    }

    public BootstrapContext getBootstrapContext() {
        return bootstrapContext.get();
    }

    @Override
    public void stop() {

        final Scheduler s = scheduler.getAndSet(null);

        if (null != s) {

            if (null != startThread.get()) {
                startThread.get().interrupt();
            }

            long timeout = SystemInstance.get().getOptions().get(QuartzResourceAdapter.OPENEJB_QUARTZ_TIMEOUT, 10000L);

            if (timeout < 1000L) {
                timeout = 1000L;
            }

            if (timeout > 60000L) {
                timeout = 60000L;
            }

            final CountDownLatch shutdownWait = new CountDownLatch(1);

            Thread stopThread = new Thread("Quartz Scheduler Requested Stop") {

                @Override
                public void run() {
                    try {
                        s.getListenerManager().addSchedulerListener(new SchedulerListenerSupport() {

                            @Override
                            public void schedulerShutdown() {
                                shutdownWait.countDown();
                            }
                        });

                        //Shutdown, but give running jobs a chance to complete.
                        //User scheduled jobs should really implement InterruptableJob
                        s.shutdown(true);
                    } catch (final Throwable e) {
                        QuartzResourceAdapter.this.ex.set(e);
                        shutdownWait.countDown();
                    }
                }
            };

            stopThread.setDaemon(true);
            stopThread.start();

            boolean stopped = false;
            try {
                stopped = shutdownWait.await(timeout, TimeUnit.MILLISECONDS);
            } catch (final InterruptedException e) {
                //Ignore
            }

            try {
                if (!stopped || !s.isShutdown()) {

                    stopThread = new Thread("Quartz Scheduler Forced Stop") {

                        @Override
                        public void run() {
                            try {
                                //Force a shutdown without waiting for jobs to complete.
                                s.shutdown(false);
                                Logger.getInstance(LogCategory.OPENEJB, "org.apache.openejb.util.resources").warning("Forced Quartz stop - Jobs may be incomplete");
                            } catch (final Throwable e) {
                                QuartzResourceAdapter.this.ex.set(e);
                            }
                        }
                    };

                    stopThread.setDaemon(true);
                    stopThread.start();

                    try {
                        //Give the forced shutdown a chance to complete
                        stopThread.join(timeout);
                    } catch (final InterruptedException e) {
                        //Ignore
                    }
                }
            } catch (final Throwable e) {
                ex.set(e);
            }
        }

        this.bootstrapContext.set(null);

        if (null != ex.get()) {
            Logger.getInstance(LogCategory.OPENEJB, "org.apache.openejb.util.resources").warning("Error stopping Quartz Scheduler", ex.get());
        } else {
            Logger.getInstance(LogCategory.OPENEJB, "org.apache.openejb.util.resources").info("Stopped Quartz Scheduler");
        }
    }

    @Override
    public void endpointActivation(final MessageEndpointFactory messageEndpointFactory, final ActivationSpec activationSpec) throws ResourceException {

        final Scheduler s = scheduler.get();
        if (null == s) {
            throw new ResourceException("Quartz Scheduler is not available");
        }

        try {

            final JobSpec spec = (JobSpec) activationSpec;

            final MessageEndpoint endpoint = messageEndpointFactory.createEndpoint(null);
            spec.setEndpoint(endpoint);

            final Job job = (Job) endpoint;

            final JobDataMap jobDataMap = spec.getDetail().getJobDataMap();
            jobDataMap.put(Data.class.getName(), new Data(job));

            s.scheduleJob(spec.getDetail(), spec.getTrigger());
        } catch (final SchedulerException e) {
            throw new ResourceException("Failed to schedule job", e);
        }
    }

    @Override
    public void endpointDeactivation(final MessageEndpointFactory messageEndpointFactory, final ActivationSpec activationSpec) {

        final Scheduler s = scheduler.get();
        if (null == s) {
            throw new IllegalStateException("Quartz Scheduler is not available");
        }

        JobSpec spec = null;

        try {
            spec = (JobSpec) activationSpec;
            s.deleteJob(spec.jobKey());

        } catch (final SchedulerException e) {
            throw new IllegalStateException("Failed to delete job", e);
        } finally {
            if (null != spec) {
                spec.getEndpoint().release();
            }
        }
    }

    public static class JobEndpoint implements Job {

        private static Method method;

        @Override
        public void execute(final JobExecutionContext execution) throws JobExecutionException {

            MessageEndpoint endpoint = null;
            JobExecutionException ex = null;

            try {

                final JobDataMap jobDataMap = execution.getJobDetail().getJobDataMap();

                final Data data = Data.class.cast(jobDataMap.get(Data.class.getName()));

                final Job job = data.job;

                if (null == method) {
                    method = job.getClass().getMethod("execute", JobExecutionContext.class);
                }

                endpoint = (MessageEndpoint) job;
                endpoint.beforeDelivery(method);

                job.execute(execution);

            } catch (final NoSuchMethodException e) {
                throw new IllegalStateException(e);
            } catch (final ResourceException e) {
                ex = new JobExecutionException(e);
            } catch (final Throwable t) {
                ex = new JobExecutionException(new Exception(t));
            } finally {

                if (null != endpoint) {
                    try {
                        endpoint.afterDelivery();
                    } catch (final ResourceException e) {
                        ex = new JobExecutionException(e);
                    }
                }
            }

            if (null != ex) {
                throw ex;
            }
        }
    }

    /**
     * A private inner class is used so the key and value are not publicly visible.
     * This is standard OpenEJB practice for all "public storage" maps as it prevents
     * outside code from becoming dependent on or tampering with the private data.
     */
    private static final class Data {

        private final Job job;

        private Data(final Job job) {
            this.job = job;
        }
    }

    @Override
    public XAResource[] getXAResources(final ActivationSpec[] activationSpecs) throws ResourceException {
        return new XAResource[0];
    }
}
