// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "storage/browser/fileapi/file_system_url.h"

#include <sstream>

#include "base/logging.h"
#include "base/strings/string_util.h"
#include "net/base/escape.h"
#include "storage/common/fileapi/file_system_types.h"
#include "storage/common/fileapi/file_system_util.h"

namespace storage {

namespace {

}  // namespace

FileSystemURL::FileSystemURL()
    : is_valid_(false),
      mount_type_(kFileSystemTypeUnknown),
      type_(kFileSystemTypeUnknown),
      mount_option_(COPY_SYNC_OPTION_NO_SYNC) {
}

// static
FileSystemURL FileSystemURL::CreateForTest(const GURL& url) {
  return FileSystemURL(url);
}

FileSystemURL FileSystemURL::CreateForTest(const GURL& origin,
                                           FileSystemType mount_type,
                                           const base::FilePath& virtual_path) {
  return FileSystemURL(origin, mount_type, virtual_path);
}

FileSystemURL FileSystemURL::CreateForTest(
    const GURL& origin,
    FileSystemType mount_type,
    const base::FilePath& virtual_path,
    const std::string& mount_filesystem_id,
    FileSystemType cracked_type,
    const base::FilePath& cracked_path,
    const std::string& filesystem_id,
    const FileSystemMountOption& mount_option) {
  return FileSystemURL(origin,
                       mount_type,
                       virtual_path,
                       mount_filesystem_id,
                       cracked_type,
                       cracked_path,
                       filesystem_id,
                       mount_option);
}

FileSystemURL::FileSystemURL(const GURL& url)
    : mount_type_(kFileSystemTypeUnknown),
      type_(kFileSystemTypeUnknown),
      mount_option_(COPY_SYNC_OPTION_NO_SYNC) {
  is_valid_ = ParseFileSystemSchemeURL(url, &origin_, &mount_type_,
                                       &virtual_path_);
  path_ = virtual_path_;
  type_ = mount_type_;
}

FileSystemURL::FileSystemURL(const GURL& origin,
                             FileSystemType mount_type,
                             const base::FilePath& virtual_path)
    : is_valid_(true),
      origin_(origin),
      mount_type_(mount_type),
      virtual_path_(virtual_path.NormalizePathSeparators()),
      type_(mount_type),
      path_(virtual_path.NormalizePathSeparators()),
      mount_option_(COPY_SYNC_OPTION_NO_SYNC) {
}

FileSystemURL::FileSystemURL(const GURL& origin,
                             FileSystemType mount_type,
                             const base::FilePath& virtual_path,
                             const std::string& mount_filesystem_id,
                             FileSystemType cracked_type,
                             const base::FilePath& cracked_path,
                             const std::string& filesystem_id,
                             const FileSystemMountOption& mount_option)
    : is_valid_(true),
      origin_(origin),
      mount_type_(mount_type),
      virtual_path_(virtual_path.NormalizePathSeparators()),
      mount_filesystem_id_(mount_filesystem_id),
      type_(cracked_type),
      path_(cracked_path.NormalizePathSeparators()),
      filesystem_id_(filesystem_id),
      mount_option_(mount_option) {
}

FileSystemURL::~FileSystemURL() {}

GURL FileSystemURL::ToGURL() const {
  if (!is_valid_)
    return GURL();

  std::string url = GetFileSystemRootURI(origin_, mount_type_).spec();
  if (url.empty())
    return GURL();

  // Exactly match with DOMFileSystemBase::createFileSystemURL()'s encoding
  // behavior, where the path is escaped by KURL::encodeWithURLEscapeSequences
  // which is essentially encodeURIComponent except '/'.
  std::string escaped = net::EscapeQueryParamValue(
      virtual_path_.NormalizePathSeparatorsTo('/').AsUTF8Unsafe(),
      false /* use_plus */);
  ReplaceSubstringsAfterOffset(&escaped, 0, "%2F", "/");
  url.append(escaped);

  // Build nested GURL.
  return GURL(url);
}

std::string FileSystemURL::DebugString() const {
  if (!is_valid_)
    return "invalid filesystem: URL";
  std::ostringstream ss;
  ss << GetFileSystemRootURI(origin_, mount_type_);

  // filesystem_id_ will be non empty for (and only for) cracked URLs.
  if (!filesystem_id_.empty()) {
    ss << virtual_path_.value();
    ss << " (";
    ss << GetFileSystemTypeString(type_) << "@" << filesystem_id_ << ":";
    ss << path_.value();
    ss << ")";
  } else {
    ss << path_.value();
  }
  return ss.str();
}

bool FileSystemURL::IsParent(const FileSystemURL& child) const {
  return IsInSameFileSystem(child) &&
         path().IsParent(child.path());
}

bool FileSystemURL::IsInSameFileSystem(const FileSystemURL& other) const {
  return origin() == other.origin() &&
         type() == other.type() &&
         filesystem_id() == other.filesystem_id();
}

bool FileSystemURL::operator==(const FileSystemURL& that) const {
  return origin_ == that.origin_ &&
      type_ == that.type_ &&
      path_ == that.path_ &&
      filesystem_id_ == that.filesystem_id_ &&
      is_valid_ == that.is_valid_;
}

bool FileSystemURL::Comparator::operator()(const FileSystemURL& lhs,
                                           const FileSystemURL& rhs) const {
  DCHECK(lhs.is_valid_ && rhs.is_valid_);
  if (lhs.origin_ != rhs.origin_)
    return lhs.origin_ < rhs.origin_;
  if (lhs.type_ != rhs.type_)
    return lhs.type_ < rhs.type_;
  if (lhs.filesystem_id_ != rhs.filesystem_id_)
    return lhs.filesystem_id_ < rhs.filesystem_id_;
  return lhs.path_ < rhs.path_;
}

}  // namespace storage
