// Copyright 2018 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.

#include "base/files/file_enumerator.h"

#include "base/files/file_util.h"
#include "base/threading/thread_restrictions.h"
#include "starboard/common/string.h"
#include "starboard/configuration_constants.h"
#include "starboard/directory.h"
#include "starboard/file.h"
#include "starboard/memory.h"

namespace base {

// FileEnumerator::FileInfo ----------------------------------------------------

FileEnumerator::FileInfo::FileInfo() {
  SbMemorySet(&sb_info_, 0, sizeof(sb_info_));
}

bool FileEnumerator::FileInfo::IsDirectory() const {
  return sb_info_.is_directory;
}

FilePath FileEnumerator::FileInfo::GetName() const {
  return filename_;
}

int64_t FileEnumerator::FileInfo::GetSize() const {
  return sb_info_.size;
}

base::Time FileEnumerator::FileInfo::GetLastModifiedTime() const {
  return base::Time::FromSbTime(sb_info_.last_modified);
}

// FileEnumerator --------------------------------------------------------------

FileEnumerator::FileEnumerator(const FilePath &root_path,
                               bool recursive,
                               int file_type)
    : FileEnumerator(root_path, recursive, file_type, FilePath::StringType(),
                     FolderSearchPolicy::MATCH_ONLY) {}

FileEnumerator::FileEnumerator(const FilePath &root_path,
                               bool recursive,
                               int file_type,
                               const FilePath::StringType &pattern)
    : FileEnumerator(root_path, recursive, file_type, pattern,
                     FolderSearchPolicy::MATCH_ONLY) {}

FileEnumerator::FileEnumerator(const FilePath& root_path,
                               bool recursive,
                               int file_type,
                               const FilePath::StringType& pattern,
                               FolderSearchPolicy folder_search_policy)
    : current_directory_entry_(0),
      root_path_(root_path),
      recursive_(recursive),
      file_type_(file_type),
      pattern_(pattern),
      folder_search_policy_(folder_search_policy) {
  // INCLUDE_DOT_DOT must not be specified if recursive.
  DCHECK(!(recursive && (INCLUDE_DOT_DOT & file_type_)));
  // The Windows version of this code appends the pattern to the root_path,
  // potentially only matching against items in the top-most directory.
  // Do the same here.
  if (pattern.empty()) {
    pattern_ = FilePath::StringType();
  }
  pending_paths_.push(root_path);
}

FileEnumerator::~FileEnumerator() = default;

//static
std::vector<FileEnumerator::FileInfo> FileEnumerator::ReadDirectory(
    const FilePath& source) {
  AssertBlockingAllowed();
  SbDirectory dir = SbDirectoryOpen(source.value().c_str(), NULL);
  if (!SbDirectoryIsValid(dir)) {
    return std::vector<FileEnumerator::FileInfo>();
  }

  auto GenerateEntry = [source](std::string filename) {
    FileEnumerator::FileInfo info;
    info.filename_ = FilePath(filename);

    FilePath full_name = source.Append(filename);
    // TODO: Make sure this follows symlinks on relevant platforms.
    if (!SbFileGetPathInfo(full_name.value().c_str(), &info.sb_info_)) {
      DPLOG(ERROR) << "Couldn't SbFileGetInfo on " << full_name.value();
      SbMemorySet(&info.sb_info_, 0, sizeof(info.sb_info_));
    }
    return info;
  };

  std::vector<FileEnumerator::FileInfo> ret;
  // We test if SbDirectoryGetNext returns parent directory file descriptor(..)
  // because the definition of SbDirectoryGetNext does not guarantee that.
  bool found_dot_dot = false;

#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
  std::vector<char> entry(kSbFileMaxName);

  while (SbDirectoryGetNext(dir, entry.data(), entry.size())) {
    const char dot_dot_str[] = "..";
    if (!SbStringCompare(entry.data(), dot_dot_str, sizeof(dot_dot_str))) {
      found_dot_dot = true;
    }
    ret.push_back(GenerateEntry(entry.data()));
  }
#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
  SbDirectoryEntry entry;

  while (SbDirectoryGetNext(dir, &entry)) {
    const char dot_dot_str[] = "..";
    if (!SbStringCompare(entry.name, dot_dot_str, sizeof(dot_dot_str))) {
      found_dot_dot = true;
    }
    ret.push_back(GenerateEntry(entry.name));
  }
#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION

  if (!found_dot_dot) {
    ret.push_back(GenerateEntry(".."));
  }

  ignore_result(SbDirectoryClose(dir));
  return ret;
}

FilePath FileEnumerator::Next() {
  AssertBlockingAllowed();

  ++current_directory_entry_;

  // While we've exhausted the entries in the current directory, do the next
  while (current_directory_entry_ >= directory_entries_.size()) {
    if (pending_paths_.empty()) {
      return FilePath();
    }

    root_path_ = pending_paths_.top();
    root_path_ = root_path_.StripTrailingSeparators();
    pending_paths_.pop();

    std::vector<FileInfo> entries = ReadDirectory(root_path_);

    directory_entries_.clear();
    current_directory_entry_ = 0;
    for (const auto& file_info : entries) {
      FilePath full_path = root_path_.Append(file_info.filename_);
      if (ShouldSkip(full_path)) {
        continue;
      }

      if (pattern_.size()) {
        NOTREACHED() << "Patterns not supported in Starboard.";
        continue;
      }

      if (recursive_ && file_info.sb_info_.is_directory) {
        pending_paths_.push(full_path);
      }

      if ((file_info.sb_info_.is_directory && (file_type_ & DIRECTORIES)) ||
          (!file_info.sb_info_.is_directory && (file_type_ & FILES))) {
        directory_entries_.push_back(file_info);
      }
    }
  }

  return
      root_path_.Append(directory_entries_[current_directory_entry_].filename_);
}

FileEnumerator::FileInfo FileEnumerator::GetInfo() const {
  return directory_entries_[current_directory_entry_];
}

}  // namespace base
