/*
 * Copyright (C) 2009 The Guava Authors
 *
 * Licensed 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 com.google.common.util.concurrent;

import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Supplier;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.time.Duration;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Base class for services that can implement {@link #startUp}, {@link #run} and {@link #shutDown}
 * methods. This class uses a single thread to execute the service; consider {@link AbstractService}
 * if you would like to manage any threading manually.
 *
 * @author Jesse Wilson
 * @since 1.0
 */
@GwtIncompatible
public abstract class AbstractExecutionThreadService implements Service {
  private static final Logger logger =
      Logger.getLogger(AbstractExecutionThreadService.class.getName());

  /* use AbstractService for state management */
  private final Service delegate =
      new AbstractService() {
        @Override
        protected final void doStart() {
          Executor executor =
              MoreExecutors.renamingDecorator(
                  executor(),
                  new Supplier<String>() {
                    @Override
                    public String get() {
                      return serviceName();
                    }
                  });
          executor.execute(
              new Runnable() {
                @Override
                public void run() {
                  try {
                    startUp();
                    notifyStarted();
                    // If stopAsync() is called while starting we may be in the STOPPING state in
                    // which case we should skip right down to shutdown.
                    if (isRunning()) {
                      try {
                        AbstractExecutionThreadService.this.run();
                      } catch (Throwable t) {
                        try {
                          shutDown();
                        } catch (Exception ignored) {
                          // TODO(lukes): if guava ever moves to java7, this would be a good
                          // candidate for a suppressed exception, or maybe we could generalize
                          // Closer.Suppressor
                          logger.log(
                              Level.WARNING,
                              "Error while attempting to shut down the service after failure.",
                              ignored);
                        }
                        notifyFailed(t);
                        return;
                      }
                    }

                    shutDown();
                    notifyStopped();
                  } catch (Throwable t) {
                    notifyFailed(t);
                  }
                }
              });
        }

        @Override
        protected void doStop() {
          triggerShutdown();
        }

        @Override
        public String toString() {
          return AbstractExecutionThreadService.this.toString();
        }
      };

  /** Constructor for use by subclasses. */
  protected AbstractExecutionThreadService() {}

  /**
   * Start the service. This method is invoked on the execution thread.
   *
   * <p>By default this method does nothing.
   */
  protected void startUp() throws Exception {}

  /**
   * Run the service. This method is invoked on the execution thread. Implementations must respond
   * to stop requests. You could poll for lifecycle changes in a work loop:
   *
   * <pre>
   *   public void run() {
   *     while ({@link #isRunning()}) {
   *       // perform a unit of work
   *     }
   *   }
   * </pre>
   *
   * <p>...or you could respond to stop requests by implementing {@link #triggerShutdown()}, which
   * should cause {@link #run()} to return.
   */
  protected abstract void run() throws Exception;

  /**
   * Stop the service. This method is invoked on the execution thread.
   *
   * <p>By default this method does nothing.
   */
  // TODO: consider supporting a TearDownTestCase-like API
  protected void shutDown() throws Exception {}

  /**
   * Invoked to request the service to stop.
   *
   * <p>By default this method does nothing.
   *
   * <p>Currently, this method is invoked while holding a lock. If an implementation of this method
   * blocks, it can prevent this service from changing state. If you need to performing a blocking
   * operation in order to trigger shutdown, consider instead registering a listener and
   * implementing {@code stopping}. Note, however, that {@code stopping} does not run at exactly the
   * same times as {@code triggerShutdown}.
   */
  @Beta
  protected void triggerShutdown() {}

  /**
   * Returns the {@link Executor} that will be used to run this service. Subclasses may override
   * this method to use a custom {@link Executor}, which may configure its worker thread with a
   * specific name, thread group or priority. The returned executor's {@link
   * Executor#execute(Runnable) execute()} method is called when this service is started, and should
   * return promptly.
   *
   * <p>The default implementation returns a new {@link Executor} that sets the name of its threads
   * to the string returned by {@link #serviceName}
   */
  protected Executor executor() {
    return new Executor() {
      @Override
      public void execute(Runnable command) {
        MoreExecutors.newThread(serviceName(), command).start();
      }
    };
  }

  @Override
  public String toString() {
    return serviceName() + " [" + state() + "]";
  }

  @Override
  public final boolean isRunning() {
    return delegate.isRunning();
  }

  @Override
  public final State state() {
    return delegate.state();
  }

  /** @since 13.0 */
  @Override
  public final void addListener(Listener listener, Executor executor) {
    delegate.addListener(listener, executor);
  }

  /** @since 14.0 */
  @Override
  public final Throwable failureCause() {
    return delegate.failureCause();
  }

  /** @since 15.0 */
  @CanIgnoreReturnValue
  @Override
  public final Service startAsync() {
    delegate.startAsync();
    return this;
  }

  /** @since 15.0 */
  @CanIgnoreReturnValue
  @Override
  public final Service stopAsync() {
    delegate.stopAsync();
    return this;
  }

  /** @since 15.0 */
  @Override
  public final void awaitRunning() {
    delegate.awaitRunning();
  }

  /** @since 28.0 */
  @Override
  public final void awaitRunning(Duration timeout) throws TimeoutException {
    Service.super.awaitRunning(timeout);
  }

  /** @since 15.0 */
  @Override
  public final void awaitRunning(long timeout, TimeUnit unit) throws TimeoutException {
    delegate.awaitRunning(timeout, unit);
  }

  /** @since 15.0 */
  @Override
  public final void awaitTerminated() {
    delegate.awaitTerminated();
  }

  /** @since 28.0 */
  @Override
  public final void awaitTerminated(Duration timeout) throws TimeoutException {
    Service.super.awaitTerminated(timeout);
  }

  /** @since 15.0 */
  @Override
  public final void awaitTerminated(long timeout, TimeUnit unit) throws TimeoutException {
    delegate.awaitTerminated(timeout, unit);
  }

  /**
   * Returns the name of this service. {@link AbstractExecutionThreadService} may include the name
   * in debugging output.
   *
   * <p>Subclasses may override this method.
   *
   * @since 14.0 (present in 10.0 as getServiceName)
   */
  protected String serviceName() {
    return getClass().getSimpleName();
  }
}
