// Copyright 2013 Google Inc. All Rights Reserved.
//
// 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 com.google.common.base.Preconditions;
import com.google.enterprise.adaptor.DocId;

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.Path;
import java.nio.file.Paths;
import java.util.concurrent.BlockingQueue;
import java.util.Iterator;

class MockFileDelegate implements FileDelegate {

  private final MockFile root;

  MockFileDelegate(MockFile root) {
    Preconditions.checkNotNull(root, "root cannot be null");
    this.root = root;
  }

  /**
   * Returns the {@link MockFile} identified by the supplied {@link Path}.
   * @throws FileNotFoundException if the file is not found.
   */
  MockFile getFile(Path doc) throws FileNotFoundException {
    Preconditions.checkNotNull(doc, "doc cannot be null");
    MockFile file = root;
    Iterator<Path> iter = doc.iterator();
    if (doc.getRoot() != null) {
      // Using startsWith because Path adds a trailing backslash to
      // UNC roots.  The second check accounts for Windows Path
      // implementation flipping slashes on Unix paths.
      if (!(doc.getRoot().toString().startsWith(root.getPath()) ||
          root.getPath().equals(doc.getRoot().toString().replace('\\', '/')))) {
        throw new FileNotFoundException("not found: " + doc.toString());
      }
    } else if (iter.hasNext()) {
      if (!(root.getPath().equals(iter.next().toString()))) {
        throw new FileNotFoundException("not found: " + doc.toString());
      }
    }
    while (iter.hasNext()) {
      file = file.getChild(iter.next().toString());
    }
    return file;
  }

  @Override
  public Path getPath(String pathname) throws IOException {
    Preconditions.checkNotNull(pathname, "pathname cannot be null");
    return Paths.get(pathname);
  }

  @Override
  public boolean isDirectory(Path doc) throws IOException {
    try {
      return getFile(doc).isDirectory();
    } catch (FileNotFoundException e) {
      return false;
    }
  }

  @Override
  public boolean isRegularFile(Path doc) throws IOException {
    try {
      return getFile(doc).isRegularFile();
    } catch (FileNotFoundException e) {
      return false;
    }
  }

  @Override
  public boolean isHidden(Path doc) throws IOException {
    try {
      return getFile(doc).isHidden();
    } catch (FileNotFoundException e) {
      return false;
    }
  }

  @Override
  public BasicFileAttributes readBasicAttributes(Path doc) throws IOException {
    return getFile(doc).readBasicAttributes();
  }

  @Override
  public void setLastAccessTime(Path doc, FileTime time) throws IOException {
    getFile(doc).setLastAccessTime(time);
  }

  @Override
  public String probeContentType(Path doc) throws IOException {
    return getFile(doc).getContentType();
  }

  @Override
  public InputStream newInputStream(Path doc) throws IOException {
    return getFile(doc).newInputStream();
  }

  @Override
  public DirectoryStream<Path> newDirectoryStream(Path doc) throws IOException {
    return getFile(doc).newDirectoryStream();
  }

  @Override
  public DocId newDocId(Path doc) throws IOException {
    String id = doc.toString().replace('\\', '/');
    if (isDirectory(doc) && !id.endsWith("/")) {
      id += "/";
    }
    if (id.startsWith("//")) {
      // String.replaceFirst uses regular expression string and replacement
      // so they need to be escaped appropriately. The above String.replace
      // does NOT use expressions so regex escaping is not needed.
      id = id.replaceFirst("//", "\\\\\\\\");
    }
    return new DocId(id);
  }

  @Override
  public AclFileAttributeViews getAclViews(Path doc) throws IOException {
    MockFile file = getFile(doc);
    return new AclFileAttributeViews(file.getAclView(),
                                     file.getInheritedAclView());
  }

  @Override
  public AclFileAttributeView getShareAclView(Path doc) throws IOException {
    return root.getShareAclView();
  }

  @Override
  public AclFileAttributeView getDfsShareAclView(Path doc) throws IOException {
    return root.getDfsShareAclView();
  }

  @Override
  public Path getDfsUncActiveStorageUnc(Path doc) throws IOException {
    return root.getDfsUncActiveStorageUnc();
  }

  @Override
  public void startMonitorPath(Path watchPath, BlockingQueue<Path> queue)
    throws IOException {
    // TODO (bmj): implementation
  }

  @Override
  public void stopMonitorPath() {
    // TODO (bmj): implementation
  }

  @Override
  public void destroy() {
    stopMonitorPath();
  }
}
