// Copyright (C) 2009 The Android Open Source Project
//
// 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.gerrit.pgm.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

public class RuntimeShutdown {
  private static final ShutdownCallback cb = new ShutdownCallback();

  /** Add a task to be performed when graceful shutdown is requested. */
  public static void add(final Runnable task) {
    if (!cb.add(task)) {
      // If the shutdown has already begun we cannot enqueue a new
      // task. Instead trigger the task in the caller, without any
      // of our locks held.
      //
      task.run();
    }
  }

  /** Wait for the JVM shutdown to occur. */
  public static void waitFor() {
    cb.waitForShutdown();
  }

  private RuntimeShutdown() {
  }

  private static class ShutdownCallback extends Thread {
    private static final Logger log =
        LoggerFactory.getLogger(ShutdownCallback.class);

    private final List<Runnable> tasks = new ArrayList<>();
    private boolean shutdownStarted;
    private boolean shutdownComplete;

    ShutdownCallback() {
      setName("ShutdownCallback");
    }

    boolean add(final Runnable newTask) {
      synchronized (this) {
        if (!shutdownStarted && !shutdownComplete) {
          if (tasks.isEmpty()) {
            Runtime.getRuntime().addShutdownHook(this);
          }
          tasks.add(newTask);
          return true;

        } else {
          // We don't permit adding a task once shutdown has started.
          //
          return false;
        }
      }
    }

    @Override
    public void run() {
      log.debug("Graceful shutdown requested");

      List<Runnable> taskList;
      synchronized (this) {
        shutdownStarted = true;
        taskList = tasks;
      }

      for (Runnable task : taskList) {
        try {
          task.run();
        } catch (Exception err) {
          log.error("Cleanup task failed", err);
        }
      }

      log.debug("Shutdown complete");

      synchronized (this) {
        shutdownComplete = true;
        notifyAll();
      }
    }

    void waitForShutdown() {
      synchronized (this) {
        while (!shutdownComplete) {
          try {
            wait();
          } catch (InterruptedException e) {
            return;
          }
        }
      }
    }
  }
}
