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

import org.apache.openejb.BeanContext;
import org.apache.openejb.MethodContext;
import org.apache.openejb.loader.SystemInstance;
import org.apache.openejb.spi.ContainerSystem;
import org.apache.openejb.util.LogCategory;
import org.apache.openejb.util.Logger;
import org.apache.openejb.quartz.Scheduler;
import org.apache.openejb.quartz.SchedulerException;
import org.apache.openejb.quartz.Trigger;
import org.apache.openejb.quartz.TriggerKey;
import org.apache.openejb.quartz.impl.triggers.AbstractTrigger;

import javax.ejb.EJBException;
import javax.ejb.Timer;
import javax.ejb.TimerConfig;
import javax.transaction.Status;
import javax.transaction.Synchronization;
import javax.transaction.Transaction;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;

public abstract class TimerData implements Serializable {

    private static final long serialVersionUID = 1L;

    public static final String OPEN_EJB_TIMEOUT_TRIGGER_NAME_PREFIX = "OPEN_EJB_TIMEOUT_TRIGGER_";
    public static final String OPEN_EJB_TIMEOUT_TRIGGER_GROUP_NAME = "OPEN_EJB_TIMEOUT_TRIGGER_GROUP";

    private static final Logger log = Logger.getInstance(LogCategory.TIMER, "org.apache.openejb.util.resources");
    private long id;
    private EjbTimerServiceImpl timerService;
    private String deploymentId;
    private Object primaryKey;
    private Method timeoutMethod;

    private Object info;
    private boolean persistent;
    private boolean autoScheduled;

    protected AbstractTrigger<?> trigger;

    protected Scheduler scheduler;

    public void setScheduler(final Scheduler scheduler) {
        this.scheduler = scheduler;
    }

    // EJB Timer object given to user code
    private Timer timer;

    /**
     * Is this a new timer?  A new timer must be scheduled with the java.util.Timer
     * when the transaction commits.
     */
    private boolean newTimer;

    /**
     * Has this timer been cancelled? A canceled timer must be rescheduled with the
     * java.util.Timer if the transaction is rolled back
     */
    private boolean cancelled;

    private boolean stopped;

    /**
     * Has this timer been registered with the transaction for callbacks?  We remember
     * when we are registered to avoid multiple registrations.
     */
    private boolean synchronizationRegistered;

    /**
     * Used to set timer to expired state after the timeout callback method has been successfully invoked.
     * only apply to
     * 1, Single action timer
     * 2, Calendar timer there are no future timeout.
     */
    private boolean expired;

    public TimerData(final long id,
                     final EjbTimerServiceImpl timerService,
                     final String deploymentId,
                     final Object primaryKey,
                     final Method timeoutMethod,
                     final TimerConfig timerConfig) {
        this.id = id;
        this.timerService = timerService;
        this.deploymentId = deploymentId;
        this.primaryKey = primaryKey;
        this.info = timerConfig == null ? null : timerConfig.getInfo();
        this.persistent = timerConfig == null || timerConfig.isPersistent();
        this.timer = new TimerImpl(this);
        this.timeoutMethod = timeoutMethod;
    }

    private void writeObject(final ObjectOutputStream out) throws IOException {
        doWriteObject(out);
    }

    protected void doWriteObject(final ObjectOutputStream out) throws IOException {
        out.writeLong(id);
        out.writeUTF(deploymentId);
        out.writeBoolean(persistent);
        out.writeBoolean(autoScheduled);
        out.writeObject(timer);
        out.writeObject(primaryKey);
        out.writeObject(timerService);
        out.writeObject(info);
        out.writeObject(trigger);
        out.writeUTF(timeoutMethod.getName());
    }

    private void readObject(final ObjectInputStream in) throws IOException {
        doReadObject(in);
    }

    protected void doReadObject(final ObjectInputStream in) throws IOException {
        id = in.readLong();
        deploymentId = in.readUTF();
        persistent = in.readBoolean();
        autoScheduled = in.readBoolean();

        try {
            timer = (Timer) in.readObject();
            primaryKey = in.readObject();
            timerService = (EjbTimerServiceImpl) in.readObject();
            info = in.readObject();
            trigger = AbstractTrigger.class.cast(in.readObject());
        } catch (final ClassNotFoundException e) {
            throw new IOException(e);
        }

        final String mtd = in.readUTF();
        final BeanContext beanContext = SystemInstance.get().getComponent(ContainerSystem.class).getBeanContext(deploymentId);
        scheduler = timerService.getScheduler();
        for (final Iterator<Map.Entry<Method, MethodContext>> it = beanContext.iteratorMethodContext(); it.hasNext(); ) {
            final MethodContext methodContext = it.next().getValue();
            /* this doesn't work in all cases
            if (methodContext.getSchedules().isEmpty()) {
                continue;
            }
            */

            final Method method = methodContext.getBeanMethod();
            if (method != null && method.getName().equals(mtd)) { // maybe we should check parameters too
                setTimeoutMethod(method);
                break;
            }
        }
    }

    public void stop() {
        if (trigger != null) {
            try {
                final Scheduler s = timerService.getScheduler();

                if (!s.isShutdown()) {
                    if (!isPersistent()) {
                        s.unscheduleJob(trigger.getKey());
                    } else {
                        s.pauseTrigger(trigger.getKey());
                    }
                }
            } catch (final SchedulerException e) {
                throw new EJBException("fail to cancel the timer", e);
            }
        }
        cancelled = true;
        stopped = true;
    }

    public long getId() {
        return id;
    }

    public String getDeploymentId() {
        return deploymentId;
    }

    public Object getPrimaryKey() {
        return primaryKey;
    }

    public Object getInfo() {
        return info;
    }

    public Timer getTimer() {
        return timer;
    }

    public boolean isNewTimer() {
        return newTimer;
    }

    public void newTimer() {
        //Initialize the Quartz Trigger
        try {
            trigger = initializeTrigger();
            trigger.computeFirstFireTime(null);
            trigger.setGroup(OPEN_EJB_TIMEOUT_TRIGGER_GROUP_NAME);
            trigger.setName(OPEN_EJB_TIMEOUT_TRIGGER_NAME_PREFIX + deploymentId + "_" + id);
            newTimer = true;

            registerTimerDataSynchronization();

        } catch (final TimerExpiredException e) {
            setExpired(true);
            log.warning("Timer " + trigger + " is expired and will never trigger.");

        } catch (final TimerStoreException e) {
            throw new EJBException("Failed to register new timer data synchronization", e);
        }
    }

    public boolean isCancelled() {
        return cancelled;
    }

    public void cancel() {
        if (stopped) {
            return;
        }

        timerService.cancelled(TimerData.this);
        if (trigger != null) {
            try {
                final Scheduler s = timerService.getScheduler();

                if (!s.isShutdown()) {
                    s.unscheduleJob(trigger.getKey());
                }
            } catch (final SchedulerException e) {
                throw new EJBException("fail to cancel the timer", e);
            }
        }
        cancelled = true;
        try {
            registerTimerDataSynchronization();
        } catch (final TimerStoreException e) {
            throw new EJBException("Failed to register timer data synchronization on cancel", e);
        }
    }

    private void setTimeoutMethod(final Method timeoutMethod) {
        this.timeoutMethod = timeoutMethod;
    }

    public Method getTimeoutMethod() {
        return timeoutMethod;
    }

    private void transactionComplete(final boolean committed) throws TimerStoreException {
        if (newTimer) {
            // you are only a new timer once no matter what
            newTimer = false;

            // if our new timer was not canceled and the transaction committed
            if (!isCancelled() && committed) {
                // schedule the timer with the java.util.Timer
                timerService.schedule(TimerData.this);
            }
        } else {
            // if the tx was rolled back, reschedule the timer with the java.util.Timer
            if (!committed) {
                cancelled = false;
                timerService.addTimerData(TimerData.this);
                timerService.schedule(TimerData.this);
            }
        }
    }

    private void registerTimerDataSynchronization() throws TimerStoreException {
        if (synchronizationRegistered) {
            return;
        }

        try {
            final Transaction transaction = timerService.getTransactionManager().getTransaction();
            final int status = transaction == null ? Status.STATUS_NO_TRANSACTION : transaction.getStatus();

            if (transaction != null && status == Status.STATUS_ACTIVE || status == Status.STATUS_MARKED_ROLLBACK) {
                transaction.registerSynchronization(new TimerDataSynchronization());
                synchronizationRegistered = true;
                return;
            }
        } catch (final Exception e) {
            log.warning("Unable to register timer data transaction synchronization", e);
        }

        // there either wasn't a transaction or registration failed... call transactionComplete directly
        transactionComplete(true);
    }

    public boolean isStopped() {
        return stopped;
    }

    private class TimerDataSynchronization implements Synchronization {

        @Override
        public void beforeCompletion() {
        }

        @Override
        public void afterCompletion(final int status) {
            synchronizationRegistered = false;
            try {
                transactionComplete(status == Status.STATUS_COMMITTED);
            } catch (final TimerStoreException e) {
                throw new EJBException("Failed on afterCompletion", e);
            }
        }
    }

    public boolean isPersistent() {
        return persistent;
    }

    public Trigger getTrigger() {

        if (scheduler != null) {
            try {
                final TriggerKey key = new TriggerKey(trigger.getName(), trigger.getGroup());
                if (scheduler.checkExists(key)) {
                    return scheduler.getTrigger(key);
                }
            } catch (final SchedulerException e) {
                return null;
            }
        }

        return trigger;
    }

    public Date getNextTimeout() {

        try {
            // give the trigger 1 ms to init itself to set correct nextTimeout value.
            Thread.sleep(1);
        } catch (final InterruptedException e) {
            log.warning("Interrupted exception when waiting 1ms for the trigger to init", e);
        }

        Date nextTimeout = null;

        if (getTrigger() != null) {

            nextTimeout = getTrigger().getNextFireTime();
        }

        return nextTimeout;
    }

    public long getTimeRemaining() {
        final Date nextTimeout = getNextTimeout();
        return nextTimeout.getTime() - System.currentTimeMillis();
    }

    public boolean isExpired() {
        return expired;
    }

    public void setExpired(final boolean expired) {
        this.expired = expired;
    }

    public abstract TimerType getType();

    protected abstract AbstractTrigger<?> initializeTrigger();
}
