/**
 * 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.hadoop.hdfs.server.namenode;

import com.google.protobuf.ByteString;
import org.apache.hadoop.fs.FileAlreadyExistsException;
import org.apache.hadoop.fs.InvalidPathException;
import org.apache.hadoop.fs.Options;
import org.apache.hadoop.fs.ParentNotDirectoryException;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.permission.FsAction;
import org.apache.hadoop.hdfs.DFSUtil;
import org.apache.hadoop.hdfs.DistributedFileSystem;
import org.apache.hadoop.hdfs.protocol.HdfsFileStatus;
import org.apache.hadoop.hdfs.protocol.QuotaExceededException;
import org.apache.hadoop.hdfs.protocol.SnapshotException;
import org.apache.hadoop.hdfs.server.namenode.INode.BlocksMapUpdateInfo;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import static org.apache.hadoop.hdfs.protocol.FSLimitException.MaxDirectoryItemsExceededException;
import static org.apache.hadoop.hdfs.protocol.FSLimitException.PathComponentTooLongException;
import static org.apache.hadoop.util.Time.now;

class FSDirRenameOp {
  @Deprecated
  static RenameOldResult renameToInt(
      FSDirectory fsd, final String srcArg, final String dstArg,
      boolean logRetryCache)
      throws IOException {
    String src = srcArg;
    String dst = dstArg;
    if (NameNode.stateChangeLog.isDebugEnabled()) {
      NameNode.stateChangeLog.debug("DIR* NameSystem.renameTo: " + src +
          " to " + dst);
    }
    if (!DFSUtil.isValidName(dst)) {
      throw new IOException("Invalid name: " + dst);
    }
    FSPermissionChecker pc = fsd.getPermissionChecker();
    HdfsFileStatus resultingStat = null;
    try (RWTransaction tx = fsd.newRWTransaction().begin()) {
      // Rename does not operate on link targets
      // Do not resolveLink when checking permissions of src and dst
      // Check write access to parent of src
      Resolver.Result srcPaths = Resolver.resolveNoSymlink(tx, src);
      Resolver.Result dstPaths = Resolver.resolve(tx, dst);
      @SuppressWarnings("deprecation")
      final boolean status = renameTo(tx,
          fsd, pc, srcPaths, dstPaths, logRetryCache);
      if (status) {
        dstPaths = Resolver.resolve(tx, dst);
        resultingStat = fsd.getAuditFileInfo(dstPaths.inodesInPath());
      }
      tx.commit();
      return new RenameOldResult(status, resultingStat);
    }
  }

  /**
   * Verify quota for rename operation where srcInodes[srcInodes.length-1] moves
   * dstInodes[dstInodes.length-1]
   */
  private static void verifyQuotaForRename(
      FSDirectory fsd, FlatINodesInPath src,
      FlatINodesInPath dst) throws QuotaExceededException {
    // TODO
//    if (!fsd.getFSNamesystem().isImageLoaded() || fsd.shouldSkipQuotaChecks()) {
//      // Do not check quota if edits log is still being processed
//      return;
//    }
//    int i = 0;
//    while(src.getINode(i) == dst.getINode(i)) { i++; }
//    // src[i - 1] is the last common ancestor.
//    BlockStoragePolicySuite bsps = fsd.getBlockStoragePolicySuite();
//    final QuotaCounts delta = src.getLastINode().computeQuotaUsage(bsps);
//
//    // Reduce the required quota by dst that is being removed
//    final INode dstINode = dst.getLastINode();
//    if (dstINode != null) {
//      delta.subtract(dstINode.computeQuotaUsage(bsps));
//    }
//    FSDirectory.verifyQuota(dst, dst.length() - 1, delta, src.getINode(i - 1));
  }

  /**
   * Checks file system limits (max component length and max directory items)
   * during a rename operation.
   */
  static void verifyFsLimitsForRename(
      FSDirectory fsd, FlatINodesInPath src,
      FlatINodesInPath dst)
      throws PathComponentTooLongException, MaxDirectoryItemsExceededException {
    // TODO
//    byte[] dstChildName = dstIIP.getLastLocalName();
//    final String parentPath = dstIIP.getParentPath();
//    fsd.verifyMaxComponentLength(dstChildName, parentPath);
//    // Do not enforce max directory items if renaming within same directory.
//    if (srcIIP.getINode(-2) != dstIIP.getINode(-2)) {
//      fsd.verifyMaxDirItems(dstIIP.getINode(-2).asDirectory(), parentPath);
//    }
  }

  /**
   * <br>
   * Note: This is to be used by {@link FSEditLogLoader} only.
   * <br>
   */
  @Deprecated
  @SuppressWarnings("deprecation")
  static boolean renameForEditLog(FSDirectory fsd, String src, String dst,
      long timestamp) throws IOException {
    if (fsd.isDir(dst)) {
      dst += Path.SEPARATOR + new Path(src).getName();
    }
    try (ReplayTransaction tx = fsd.newReplayTransaction().begin()) {
      Resolver.Result srcPaths = Resolver.resolveNoSymlink(tx, src);
      Resolver.Result dstPaths = Resolver.resolveNoSymlink(tx, dst);
      return unprotectedRenameTo(tx, fsd, srcPaths, dstPaths, timestamp);
    }
  }

  /**
   * Change a path name
   *
   * @param fsd FSDirectory
   * @param src source path
   * @param dst destination path
   * @return true if rename succeeds; false otherwise
   * @deprecated See {@link #renameToInt(FSDirectory, String, String,
   * boolean, Options.Rename...)}
   */
  @Deprecated
  static boolean unprotectedRenameTo(RWTransaction ntx,
      FSDirectory fsd, Resolver.Result src, Resolver.Result dst,
      long timestamp)
      throws IOException {
    assert fsd.hasWriteLock();
    try {
      validateRenameSource(src);
    } catch (SnapshotException e) {
      throw e;
    } catch (IOException ignored) {
      return false;
    }

    // validate the destination
    if (dst.equals(src)) {
      return true;
    }

    try {
      validateDestination(src, dst);
    } catch (IOException ignored) {
      return false;
    }

    if (dst.ok()) {
      NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: " +
          "failed to rename " + src + " to " + dst + " because destination " +
          "exists");
      return false;
    }
    if (FlatNSUtil.hasNextLevelInPath(dst.src, dst.offset)) {
      NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: " +
          "failed to rename " + src.src + " to " + dst.src + " because " +
          "destination's parent does not exist");
      return false;
    }

    // TODO: Handle encrytpion
    // fsd.ezManager.checkMoveValidity(src, dst, src);
    // Ensure dst has quota to accommodate rename
    verifyFsLimitsForRename(fsd, src.inodesInPath(), dst.inodesInPath());
    verifyQuotaForRename(fsd, src.inodesInPath(), dst.inodesInPath());

    RenameOperation tx = new RenameOperation(ntx, src, dst);

    boolean added;

    // remove src
    if (!tx.removeSrc4OldRename(timestamp)) {
      return false;
    }

    added = tx.addSourceToDestination(timestamp);
    if (added) {
      return true;
    }
    NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: " +
        "failed to rename " + src.src + " to " + dst.src);
    return false;
  }

  /**
   * The new rename which has the POSIX semantic.
   */
  static Map.Entry<BlocksMapUpdateInfo, HdfsFileStatus> renameToInt(
      FSDirectory fsd, final String srcArg, final String dstArg,
      boolean logRetryCache, Options.Rename... options)
      throws IOException {
    String src = srcArg;
    String dst = dstArg;
    if (NameNode.stateChangeLog.isDebugEnabled()) {
      NameNode.stateChangeLog.debug("DIR* NameSystem.renameTo: with options -" +
                                        " " + src + " to " + dst);
    }
    if (!DFSUtil.isValidName(dst)) {
      throw new InvalidPathException("Invalid name: " + dst);
    }
    final FSPermissionChecker pc = fsd.getPermissionChecker();

    BlocksMapUpdateInfo collectedBlocks = new BlocksMapUpdateInfo();
    try (RWTransaction tx = fsd.newRWTransaction().begin()) {
      Resolver.Result srcPaths = Resolver.resolve(tx, src);
      Resolver.Result dstPaths = Resolver.resolve(tx, dst);
      renameTo(tx, fsd, pc, srcPaths, dstPaths, collectedBlocks, logRetryCache,
               options);
      dstPaths = Resolver.resolve(tx, dst);
      HdfsFileStatus resultingStat =
          fsd.getAuditFileInfo(dstPaths.inodesInPath());
      tx.commit();
      return new AbstractMap.SimpleImmutableEntry<>(
          collectedBlocks, resultingStat);
    }
  }

  static void renameTo(RWTransaction tx, FSDirectory fsd, FSPermissionChecker
      pc, Resolver.Result src, Resolver.Result dst,
      BlocksMapUpdateInfo collectedBlocks, boolean logRetryCache,
      Options.Rename... options) throws IOException {
    validateRenameSource(src);
    if (fsd.isPermissionEnabled()) {
      // Rename does not operate on link targets
      // Do not resolveLink when checking permissions of src and dst
      // Check write access to parent of src
      fsd.checkPermission(pc, src.inodesInPath(), false, null, FsAction.WRITE, null,
                          null, false);
      // TODO: Check write access to ancestor of dst
      fsd.checkPermission(pc, dst.inodesInPath(), false, FsAction.WRITE, null,
                          null, null, false);
    }

    if (NameNode.stateChangeLog.isDebugEnabled()) {
      NameNode.stateChangeLog.debug(
          "DIR* FSDirectory.renameTo: " + src + " to " + dst);
    }
    final long mtime = now();

    if (unprotectedRenameTo(tx, fsd, src, dst, mtime, collectedBlocks,
                            options)) {
      FSDirDeleteOp.incrDeletedFileCount(1);
    }
    tx.logRename(src.src, dst.src, mtime, logRetryCache, options);
  }

  /**
   * Rename src to dst.
   * <br>
   * Note: This is to be used by {@link org.apache.hadoop.hdfs.server
   * .namenode.FSEditLogLoader} only.
   * <br>
   *
   * @param fsd       FSDirectory
   * @param src       source path
   * @param dst       destination path
   * @param timestamp modification time
   * @param options   Rename options
   */
  static void renameForEditLog(
      FSDirectory fsd, String src, String dst, long timestamp,
      Options.Rename... options)
      throws IOException {
    BlocksMapUpdateInfo collectedBlocks = new BlocksMapUpdateInfo();
    boolean ret;
    try (ReplayTransaction tx = fsd.newReplayTransaction().begin()) {
      Resolver.Result srcPaths = Resolver.resolveNoSymlink(tx, src);
      Resolver.Result dstPaths = Resolver.resolveNoSymlink(tx, dst);
      ret = unprotectedRenameTo(tx, fsd, srcPaths, dstPaths,
                                timestamp, collectedBlocks, options);
      if (!collectedBlocks.getToDeleteList().isEmpty()) {
        fsd.getFSNamesystem().removeBlocksAndUpdateSafemodeTotal(collectedBlocks);
      }
    }
  }

  /**
   * Rename src to dst.
   * See {@link DistributedFileSystem#rename(Path, Path, Options.Rename...)}
   * for details related to rename semantics and exceptions.
   *
   * @param fsd             FSDirectory
   * @param src             source path
   * @param dst             destination path
   * @param timestamp       modification time
   * @param collectedBlocks blocks to be removed
   * @param options         Rename options
   * @return whether a file/directory gets overwritten in the dst path
   */
  static boolean unprotectedRenameTo(
      RWTransaction ntx, FSDirectory fsd, final Resolver.Result src,
      final Resolver.Result dst, long timestamp,
      BlocksMapUpdateInfo collectedBlocks, Options.Rename... options)
      throws IOException {
    boolean overwrite = options != null
        && Arrays.asList(options).contains(Options.Rename.OVERWRITE);

    // validate the destination
    if (dst.equals(src)) {
      throw new FileAlreadyExistsException("The source " + src +
          " and destination " + dst + " are the same");
    }

    validateDestination(src, dst);

    String error;
    if (dst.ok() && dst.inodesInPath().length() == 1) {
      error = "rename destination cannot be the root";
      NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: " +
          error);
      throw new IOException(error);
    }

    // TODO: Handle encrytion zone
    // fsd.ezManager.checkMoveValidity(srcIIP, dstIIP, src);

    if (dst.ok()) { // Destination exists
      // TODO: Validate overwrite
      // validateOverwrite(ntx, src, dst, overwrite, srcInode, dstInode);
      // TODO: Check snapshot
      // FSDirSnapshotOp.checkSnapshot(dstInode, snapshottableDirs);
    }

    if (FlatNSUtil.hasNextLevelInPath(dst.src, dst.offset)) {
      error = "rename destination parent " + dst + " not found.";
      NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: " +
          error);
      throw new FileNotFoundException(error);
    }

    FlatINode dstParent = dst.getLastINode(-2);
    if (!dstParent.isDirectory()) {
      error = "rename destination parent " + dst + " is a file.";
      NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: " +
          error);
      throw new ParentNotDirectoryException(error);
    }

    // TODO: Ensure dst has quota to accommodate rename
    // verifyFsLimitsForRename(fsd, srcIIP, dstIIP);
    // verifyQuotaForRename(fsd, srcIIP, dstIIP);

    RenameOperation tx = new RenameOperation(ntx, src, dst);

    tx.removeSrc(timestamp);

    List<Long> removedINodes = new ArrayList<>();
    List<Long> removedUCFiles = new ArrayList<>();
    if (dst.ok()) { // dst exists, remove it
      tx.removeDst(collectedBlocks, removedINodes, removedUCFiles);
    }

    // add src as dst to complete rename
    if (tx.addSourceToDestination(timestamp)) {
      if (NameNode.stateChangeLog.isDebugEnabled()) {
        NameNode.stateChangeLog.debug("DIR* FSDirectory.unprotectedRenameTo: "
                                          + src + " is renamed to " + dst);
      }

      // Collect the blocks and remove the lease for previous dst
      boolean filesDeleted = false;
      // TODO: Handle snapshots

      FSNamesystem fsn = fsd.getFSNamesystem();
      fsn.removeLeases(removedUCFiles);
      return filesDeleted;
    }

    NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: " +
        "failed to rename " + src + " to " + dst);
    throw new IOException("rename from " + src + " to " + dst + " failed.");
  }

  /**
   * @deprecated Use {@link #renameToInt(FSDirectory, String, String,
   * boolean, Options.Rename...)}
   */
  @Deprecated
  @SuppressWarnings("deprecation")
  private static boolean renameTo(
      RWTransaction tx, FSDirectory fsd,
      FSPermissionChecker pc, Resolver.Result src, Resolver.Result dst,
      boolean logRetryCache)
      throws IOException {

    Resolver.Result dstArg = dst;
    // Note: We should not be doing this.  This is move() not renameTo().
    if (dst.ok() && dst.inodesInPath().getLastINode().isDirectory()) {
      String actualDst = dst.src + Path.SEPARATOR + new Path(src.src).getName();
      dst = Resolver.resolve(tx, actualDst);
    }

    if (fsd.isPermissionEnabled()) {
      fsd.checkPermission(pc, src.inodesInPath(),
                          false, null, FsAction.WRITE, null, null, false);
      // Check write access to ancestor of dst
      fsd.checkPermission(pc, dst.inodesInPath(), false, FsAction.WRITE,
                          null, null, null, false);
    }

    if (NameNode.stateChangeLog.isDebugEnabled()) {
      NameNode.stateChangeLog.debug("DIR* FSDirectory.renameTo: " + src + " to "
          + dst);
    }
    final long mtime = now();
    boolean stat = unprotectedRenameTo(tx, fsd, src, dst, mtime);
    if (stat) {
      fsd.getEditLog().logRename(src.src, dstArg.src, mtime, logRetryCache);
      return true;
    }
    return false;
  }

  private static void validateDestination(Resolver.Result src, Resolver
      .Result dst) throws IOException {
    String error;
    // TODO: Handle symlink
//    if (srcInode.isSymlink() &&
//        dst.equals(srcInode.asSymlink().getSymlinkString())) {
//      throw new FileAlreadyExistsException("Cannot rename symlink " + src
//                                               + " to its target " + dst);
//    }

    // dst cannot be a directory or a file under src
    if (dst.inodesInPath().length() > src.inodesInPath().length()) {
      List<Map.Entry<ByteString, FlatINode>> srcINodes = src.inodesInPath()
          .inodes();
      List<Map.Entry<ByteString, FlatINode>> dstINodes = dst.inodesInPath()
          .inodes();
      for (int i = 0, e = srcINodes.size(); i < e; ++i) {
        if (srcINodes.get(i).getValue().id() != dstINodes.get(i).getValue()
            .id()) {
          return;
        }
      }
      error = "Rename destination " + dst
          + " is a directory or file under source " + src;
      NameNode.stateChangeLog.warn(
          "DIR* FSDirectory.unprotectedRenameTo: " + error);
      throw new IOException(error);
    }
  }

  private static void validateOverwrite(RWTransaction tx,
      String src, String dst, boolean overwrite,
      FlatINode srcInode, FlatINode dstInode)
      throws IOException {
    String error;// It's OK to rename a file to a symlink and vice versa
    if (dstInode.isDirectory() != srcInode.isDirectory()) {
      error = "Source " + src + " and destination " + dst
          + " must both be directories";
      NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
                                       + error);
      throw new IOException(error);
    }
    if (!overwrite) { // If destination exists, overwrite flag must be true
      error = "rename destination " + dst + " already exists";
      NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
                                       + error);
      throw new FileAlreadyExistsException(error);
    }
    if (dstInode.isDirectory()) {
      try (DBChildrenView children = tx.childrenView(dstInode.id())) {
        boolean hasChildren = !children.isEmpty();
        if (hasChildren) {
          error = "rename destination directory is not empty: " + dst;
          NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
                                           + error);
          throw new IOException(error);
        }
      }
    }
  }

  private static void validateRenameSource(Resolver.Result paths)
      throws IOException {
    String error;
    if (paths.invalidPath()) {
      throw new InvalidPathException(paths.src);
    } else if (paths.notFound()) {
      error = "rename source " + paths.src + " is not found.";
      NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
                                       + error);
      throw new FileNotFoundException(error);
    } else if (paths.inodesInPath().length() == 1) {
      error = "rename source cannot be the root";
      NameNode.stateChangeLog.warn("DIR* FSDirectory.unprotectedRenameTo: "
                                       + error);
      throw new IOException(error);
    }
    // TODO: srcInode and its subtree cannot contain snapshottable
    // directories with snapshots
  }

  private static class RenameOperation {
    private final RWTransaction tx;
    private final Resolver.Result src;
    private final Resolver.Result dst;
    private final ByteString srclocalName;

    RenameOperation(
        RWTransaction tx, Resolver.Result src,
        Resolver.Result dst) {
      this.tx = tx;
      this.src = src;
      this.dst = dst;
      srclocalName = src.inodesInPath().inodes().get(
          src.inodesInPath().length() - 1).getKey();
    }

    long removeSrc(long mtime) throws IOException {
      FlatINode parent = src.inodesInPath().getLastINode(-2);
      ByteString newParent = new FlatINode.Builder()
          .mergeFrom(parent).mtime(mtime).build();
      tx.deleteChild(parent.id(), srclocalName.asReadOnlyByteBuffer());
      tx.putINode(parent.id(), newParent);
      return 1;
      // TODO: Handle quota
    }

    boolean removeSrc4OldRename(long mtime) {
      try {
        removeSrc(mtime);
        return true;
      } catch (IOException ignored) {
        return false;
      }
    }

    long removeDst(BlocksMapUpdateInfo removedBlocks,
        List<Long> removedINodes, List<Long> removedUCFiles) {
      try {
        long deleted = FSDirDeleteOp.delete(
            tx, dst, removedBlocks, removedUCFiles, now());
        return deleted;
      } catch (IOException ignored) {
      }
      return -1;
    }

    boolean addSourceToDestination(long mtime) {
      FlatINode parent = dst.ok()
          ? dst.inodesInPath().getLastINode(-2)
          : dst.inodesInPath().getLastINode();
      ByteString localName = ByteString.copyFromUtf8(
          FlatNSUtil.getNextComponent(dst.src, dst.offset));
      ByteString newParent = new FlatINode.Builder()
          .mergeFrom(parent).mtime(mtime).build();
      tx.putINode(parent.id(), newParent);
      tx.putChild(parent.id(), localName.asReadOnlyByteBuffer(),
                  src.inodesInPath().getLastINode().id());
      return true;
    }
  }

  static class RenameOldResult {
    final boolean success;
    final HdfsFileStatus auditStat;

    RenameOldResult(boolean success, HdfsFileStatus auditStat) {
      this.success = success;
      this.auditStat = auditStat;
    }
  }
}
