/*
 * 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.ode.utils.fs;

import org.apache.ode.utils.GUID;
import org.apache.ode.utils.SystemUtils;

import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.SortedSet;
import java.util.TreeSet;

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

/**
 * Convenience class for managing temporary files and cleanup on JVM exit.
 */
public class TempFileManager {

  private static final Logger __log = LoggerFactory.getLogger(TempFileManager.class);

  private static TempFileManager __singleton;
  private static File __baseDir;
  private static File __workDir;

  private SortedSet<File> _registeredFiles = new TreeSet<File>(Collections.reverseOrder(null));

  private static synchronized TempFileManager getInstance() {
    if (__singleton == null) {
      __singleton = new TempFileManager();
    }
    return __singleton;
  }

  private TempFileManager() {
    super();

    if (__baseDir == null) {
      String tmpDirPath = null;
      try {
        tmpDirPath = SystemUtils.javaTemporaryDirectory();
      }
      catch (SecurityException se) {
        __log.error("Unable to read system property for temporary directory setting; "
            + "will use default configuration.");
        tmpDirPath = "";
      }

      File tmpDir = new File(tmpDirPath);
      if (tmpDir.exists()) {
        __baseDir = tmpDir;
      }
      else {
        throw new IllegalStateException("Odd system configuration - temporary working directory "
            + tmpDirPath + " does not exist.");
      }
    }

    try {
      File odeTmp = new File(__baseDir, "ode-" + new GUID().toString());
      if (odeTmp.mkdir()) {
        __workDir = odeTmp;
        __log.debug("Set working directory to: " + __workDir.getAbsolutePath());
        this._registerTemporaryFile(__workDir);
      }
      else {
        throw new IllegalStateException("Unable to create temporary working directory in "
            + __baseDir.getPath());
      }
    }
    catch (SecurityException se) {
      throw new IllegalStateException("The security configuration is preventing the creation of a "
          + "temporary working directory.", se);
    }

  }

  /**
   * <p>
   * Set the working temporary directory.  This method can only be invoked when
   * the singleton instance is uninitialized, and the <code>File</code> passed in
   * must be both a directory and writable.
   * </p>
   * @param f the temporary working directory
   */
  public static synchronized void setWorkingDirectory(File f) {
    if (__singleton == null) {
      if (f == null) {
        __baseDir = null;
      }
      else {
        if (f.isDirectory() && f.canWrite()) {
          __baseDir = f;
          if (__log.isDebugEnabled()) {
              __log.debug("Setting base working directory: " + f);
          }
        }
        else {
          throw new IllegalArgumentException("Not a writeable directory: " + f);
        }
      }
    }
    // cannot set working directory after an instance has been created;
    // call cleanup() first.
    else {
      String msg;
      if (__baseDir != null) {
        msg = "Already initialized in base directory: " + __baseDir.getPath();
      }
      else {
        msg = "Already initialized, but no base directory set.";
      }
      throw new IllegalStateException(msg);
    }
  }

  /**
   * <p>
   * Get a temporary file, if possible, and register it for cleanup later.  In the
   * event that a temporary file cannot be created, the method will attempt to
   * create a file in the current working directory instead.
   * </p>
   *
   * @param handle a prefix to use in naming the file; probably only useful for
   * debugging.
   * @return the temporary file.
   */
  public static synchronized File getTemporaryFile(String handle) {
    return getTemporaryFile(handle, __workDir);
  }

  public static synchronized File getTemporaryFile(String handle, File parent) {
    // force initialization if necessary
    if (__singleton == null) {
      getInstance();
    }

    if (handle == null) {
      handle = "temp-";
    }

    if (parent == null) {
      parent = (__workDir != null ? __workDir : __baseDir);
    }

    File tmp;
    try {
      tmp = File.createTempFile(handle + Long.toHexString(System.currentTimeMillis()), ".tmp", parent);
    } catch (IOException ioe) {
      __log.error("Unable to create temporary file in working directory " +
          (parent == null ? "<null>; " : (parent.getPath() + "; ")) +
          "falling back to current working directory.", ioe);
      tmp = new File(handle + new GUID().toString());
    }

    registerTemporaryFile(tmp);
    return tmp;
  }

  /**
   * <p>
   * Get a temporary working directory.
   * </p>
   *
   * @param handle a prefix to use in naming the directory.
   * @return the temp directory.
   * @see #getTemporaryFile(String)
   */
  public static synchronized File getTemporaryDirectory(String handle) {
    return getTemporaryDirectory(handle,null);
  }

  public static synchronized File getTemporaryDirectory(String handle, File parent) {
    File f = getTemporaryFile(handle, parent);
    f.delete();
    f.mkdirs();
    return f;
  }

  /*
   * Register an externally created file/directory for later cleanup.
   */
  public static synchronized void registerTemporaryFile(File f) {
    getInstance()._registerTemporaryFile(f);
  }

  private synchronized void _registerTemporaryFile(File f) {
    _registeredFiles.add(f);
    if (__log.isDebugEnabled()) {
        __log.debug("Registered temporary file: " + f.getPath());
    }
  }

  /**
   * <p>
   * Clear out the temporary working directory.  This can be called by, e.g.,
   * a commandline tool or other client when it is known that all temporary
   * files can be deleted.
   * </p>
   */
  public static synchronized void cleanup() {
    if (__singleton != null) {
      __singleton._cleanup();
      __singleton = null;
    } else {
      __log.debug("No cleanup necessary.");
    }
  }

  @SuppressWarnings("unchecked")
  private synchronized void _cleanup() {
    try {
      // collect all subdirectory contents that still exist, ordered files-first
      SortedSet<File> allFiles = new TreeSet(Collections.reverseOrder(null));
      for (File f: _registeredFiles) {
        if (f.exists()) {
          allFiles.addAll(FileUtils.directoryEntriesInPath(f));
        }
      }

      if (__log.isDebugEnabled()) {
          __log.debug("cleaning up " +  allFiles.size() + " files.");
      }

      // now delete all files
      for (File f: allFiles) {
        if (__log.isDebugEnabled()) {
            __log.debug("deleting: " + f.getAbsolutePath());
        }
        if (f.exists() && !f.delete()) {
          __log.error("Unable to delete file " + f.getAbsolutePath() +
          "; this may be caused by a descriptor leak and should be reported.");
          // fall back to deletion on VM shutdown
          f.deleteOnExit();
        }
      }
    } finally {
      _registeredFiles.clear();
      __workDir = null;
      __log.debug("cleanup done.");
    }
  }

}
