// Copyright 2009 Google Inc.
//
// 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.enterprise.adaptor.fs;

import static com.google.enterprise.adaptor.fs.AclView.user;
import static com.google.enterprise.adaptor.fs.AclView.group;

import static java.nio.file.attribute.AclEntryFlag.*;
import static java.nio.file.attribute.AclEntryPermission.*;
import static java.nio.file.attribute.AclEntryType.*;

import com.google.common.base.Charsets;
import com.google.common.base.Preconditions;

import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.attribute.AclFileAttributeView;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.nio.file.DirectoryStream;
import java.nio.file.NotDirectoryException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

class MockFile {
  static final String SEPARATOR = "/";
  static final FileTime DEFAULT_FILETIME = FileTime.fromMillis(10000);
  static final AclFileAttributeView FULL_ACCESS_ACLVIEW =
      new AclView(group("Everyone").type(ALLOW)
          .perms(READ_DATA, READ_ATTRIBUTES, READ_NAMED_ATTRS, READ_ACL)
          .flags(FILE_INHERIT, DIRECTORY_INHERIT));
  static final AclFileAttributeView EMPTY_ACLVIEW = new AclView();

  private MockFile parent;
  private String name;
  private boolean isHidden = false;
  private boolean isRegularFile;
  private boolean isDirectory;
  private List<MockFile> directoryContents;
  private Path dfsUncActiveStorageUnc;
  private AclFileAttributeView dfsShareAclView;
  private AclFileAttributeView shareAclView;
  private AclFileAttributeView aclView;
  private AclFileAttributeView inheritedAclView;
  private FileTime creationTime = DEFAULT_FILETIME;
  private FileTime lastModifiedTime = DEFAULT_FILETIME;
  private FileTime lastAccessTime = DEFAULT_FILETIME;
  private String contentType;
  private byte[] fileContents;

  /**
   * Create a regular file with the specified {@code name}.
   *
   * @param name the name of the file
   */
  MockFile(String name) {
    this(name, false);
  }

  /**
   * Create a file or directory with the specified {@code name}.
   *
   * @param name the name of the file or directory
   * @param isDirectory true if this is a directory, false if regular file
   */
  MockFile(String name, boolean isDirectory) {
    Preconditions.checkNotNull(name, "name cannot be null");
    this.name = name;
    this.isRegularFile = !isDirectory;
    this.isDirectory = isDirectory;
    if (isDirectory) {
      directoryContents = new ArrayList<MockFile>();
    } else {
      setFileContents("Contents of " + name);
    }
  }

  /**
   * Add the supplied files/directories as children of this MockFile.
   * This automatically sets isDirectory and resets isRegularFile on this
   * MockFile, and registers this file as the parent of all the children.
   */
  MockFile addChildren(MockFile... children) {
    Preconditions.checkState(isDirectory, "not a directory %s", getPath());
    for (MockFile child : children) {
      child.parent = this;
      directoryContents.add(child);
    }
    return this;
  }

  /**
   * Returns the child of the given name.
   */
  MockFile getChild(String name) throws FileNotFoundException {
    Preconditions.checkNotNull(name, "name cannot be null");
    Preconditions.checkState(isDirectory, "not a directory %s", getPath());
    Iterator<MockFile> it = directoryContents.iterator();
    while (it.hasNext()) {
      MockFile f = it.next();
      if (f.name.equals(name)) {
        return f;
      }
    }
    throw new FileNotFoundException(
        "no such file: " + getPath() + SEPARATOR + name);
  }

  /**
   * Return the path to this file or directory.
   */
  String getPath() {
    if (parent == null) {
      return name;
    } else {
      String parentPath = parent.getPath();
      return (parentPath.endsWith(SEPARATOR))
             ? parentPath + name : parentPath + SEPARATOR + name;
    }
  }

  MockFile setName(String name) {
    Preconditions.checkNotNull(name, "name cannot be null");
    this.name = name;
    return this;
  }

  /**
   * Return the name to this file or directory.
   */
  String getName() {
    return name;
  }

  /**
   * Return the parent directory of this file or directory,
   * or null if there is no parent.
   */
  MockFile getParent() {
    return parent;
  }

  boolean isDirectory() throws IOException {
    return isDirectory;
  }

  /** If false, maybe a directory, pipe, device, broken link, hidden, etc. */
  MockFile setIsRegularFile(boolean isRegularFile) {
    this.isRegularFile = isRegularFile;
    return this;
  }

  boolean isRegularFile() throws IOException {
    return isRegularFile;
  }

  MockFile setIsHidden(boolean isHidden) {
    this.isHidden = isHidden;
    return this;
  }

  boolean isHidden() throws IOException {
    return isHidden;
  }

  MockFile setCreationTime(FileTime creationTime) {
    Preconditions.checkNotNull(creationTime, "time cannot be null");
    this.creationTime = creationTime;
    return this;
  }

  FileTime getCreationTime() throws IOException {
    return creationTime;
  }

  MockFile setLastModifiedTime(FileTime lastModifiedTime) {
    Preconditions.checkNotNull(lastModifiedTime, "time cannot be null");
    this.lastModifiedTime = lastModifiedTime;
    return this;
  }

  FileTime getLastModifiedTime() throws IOException {
    return lastModifiedTime;
  }

  /** Note that the adaptor calls this setter. */
  MockFile setLastAccessTime(FileTime lastAccessTime) throws IOException {
    Preconditions.checkNotNull(lastAccessTime, "time cannot be null");
    this.lastAccessTime = lastAccessTime;
    return this;
  }

  FileTime getLastAccessTime() throws IOException {
    return lastAccessTime;
  }

  BasicFileAttributes readBasicAttributes() throws IOException {
    return new MockBasicFileAttributes();
  }

  MockFile setDfsUncActiveStorageUnc(Path unc) {
    this.dfsUncActiveStorageUnc = unc;
    return this;
  }

  Path getDfsUncActiveStorageUnc() throws IOException {
    return dfsUncActiveStorageUnc;
  }

  MockFile setDfsShareAclView(AclFileAttributeView aclView) {
    this.dfsShareAclView = aclView;
    return this;
  }

  AclFileAttributeView getDfsShareAclView() throws IOException {
    return dfsShareAclView;
  }

  MockFile setShareAclView(AclFileAttributeView aclView) {
    this.shareAclView = aclView;
    return this;
  }

  AclFileAttributeView getShareAclView() throws IOException {
    return (shareAclView == null) ? FULL_ACCESS_ACLVIEW : shareAclView;
  }

  MockFile setAclView(AclFileAttributeView aclView) {
    this.aclView = aclView;
    return this;
  }

  AclFileAttributeView getAclView() throws IOException {
    if (aclView == null) {
      return (parent == null) ? FULL_ACCESS_ACLVIEW : EMPTY_ACLVIEW;
    } else {
      return aclView;
    }
  }

  MockFile setInheritedAclView(AclFileAttributeView aclView) {
    this.inheritedAclView = aclView;
    return this;
  }

  AclFileAttributeView getInheritedAclView() throws IOException {
    if (inheritedAclView == null) {
      if (parent == null) {
        // root has no inherited ACL
        return EMPTY_ACLVIEW;
      } else if (parent.parent == null) {
        // root's children inherit its ACL
        return parent.getAclView();
      } else {
        // all other children inherit from their parent
        return parent.getInheritedAclView();
      }
    } else {
      return inheritedAclView;
    }
  }

  MockFile setContentType(String contentType) {
    this.contentType = contentType;
    return this;
  }

  String getContentType() throws IOException {
    return isRegularFile ? contentType : null;
  }

  MockFile setFileContents(String fileContents) {
    Preconditions.checkNotNull(fileContents, "fileContents cannot be null");
    setFileContents(fileContents.getBytes(Charsets.UTF_8));
    if (contentType == null) {
      contentType = "text/plain";
    }
    return this;
  }

  MockFile setFileContents(byte[] fileContents) {
    Preconditions.checkState(isRegularFile, "not a regular file %s", getPath());
    Preconditions.checkNotNull(fileContents, "fileContents cannot be null");
    this.fileContents = fileContents;
    return this;
  }

  InputStream newInputStream() throws IOException {
    Preconditions.checkState(isRegularFile, "not a regular file %s", getPath());
    return new ByteArrayInputStream(fileContents);
  }

  DirectoryStream<Path> newDirectoryStream() throws IOException {
    if (!isDirectory) {
      throw new NotDirectoryException("not a directory " + getPath());
    }
    return new MockDirectoryStream(directoryContents);
  }

  @Override
  public String toString() {
    return getPath();
  }

  private class MockBasicFileAttributes implements BasicFileAttributes {

    @Override
    public Object fileKey() {
      return MockFile.this;
    }

    @Override
    public FileTime creationTime() {
      return creationTime;
    }

    @Override
    public FileTime lastAccessTime() {
      return lastAccessTime;
    }

    @Override
    public FileTime lastModifiedTime() {
      return lastModifiedTime;
    }

    @Override
    public boolean isDirectory() {
      return isDirectory;
    }

    @Override
    public boolean isRegularFile() {
      return isRegularFile;
    }

    @Override
    public boolean isOther() {
      return !(isDirectory || isRegularFile);
    }

    @Override
    public boolean isSymbolicLink() {
      return false;
    }

    @Override
    public long size() {
      if (isRegularFile && fileContents != null) {
        return fileContents.length;
      } else {
        return 0L;
      }
    }
  }

  private class MockDirectoryStream implements DirectoryStream<Path> {
    private Iterator<Path> iterator;

    MockDirectoryStream(List<MockFile> files) {
      ArrayList<Path> paths = new ArrayList<Path>();
      for (MockFile file : files) {
        paths.add(Paths.get(file.getPath()));
      }
      Collections.sort(paths);
      iterator = paths.iterator();
    }

    @Override
    public Iterator<Path> iterator() {
      Preconditions.checkState(iterator != null,
          "multiple attempts to get iterator");
      Iterator<Path> rtn = iterator;
      iterator = null;
      return rtn;
    }

    @Override
    public void close() {}
  }
}
