/*
 * Copyright (C) 2010 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "modules/filesystem/DOMFileSystemSync.h"

#include "bindings/core/v8/ExceptionState.h"
#include "core/fileapi/File.h"
#include "core/fileapi/FileError.h"
#include "modules/filesystem/DOMFilePath.h"
#include "modules/filesystem/DirectoryEntrySync.h"
#include "modules/filesystem/ErrorCallback.h"
#include "modules/filesystem/FileEntrySync.h"
#include "modules/filesystem/FileSystemCallbacks.h"
#include "modules/filesystem/FileWriterBaseCallback.h"
#include "modules/filesystem/FileWriterSync.h"
#include "platform/FileMetadata.h"
#include "public/platform/WebFileSystem.h"
#include "public/platform/WebFileSystemCallbacks.h"
#include "wtf/PtrUtil.h"
#include <memory>

namespace blink {

class FileWriterBase;

DOMFileSystemSync* DOMFileSystemSync::create(DOMFileSystemBase* fileSystem) {
  return new DOMFileSystemSync(fileSystem->m_context, fileSystem->name(),
                               fileSystem->type(), fileSystem->rootURL());
}

DOMFileSystemSync::DOMFileSystemSync(ExecutionContext* context,
                                     const String& name,
                                     FileSystemType type,
                                     const KURL& rootURL)
    : DOMFileSystemBase(context, name, type, rootURL),
      m_rootEntry(DirectoryEntrySync::create(this, DOMFilePath::root)) {}

DOMFileSystemSync::~DOMFileSystemSync() {}

void DOMFileSystemSync::reportError(ErrorCallbackBase* errorCallback,
                                    FileError::ErrorCode fileError) {
  errorCallback->invoke(fileError);
}

DirectoryEntrySync* DOMFileSystemSync::root() {
  return m_rootEntry.get();
}

namespace {

class CreateFileHelper final : public AsyncFileSystemCallbacks {
 public:
  class CreateFileResult : public GarbageCollected<CreateFileResult> {
   public:
    static CreateFileResult* create() { return new CreateFileResult(); }

    bool m_failed;
    int m_code;
    Member<File> m_file;

    DEFINE_INLINE_TRACE() { visitor->trace(m_file); }

   private:
    CreateFileResult() : m_failed(false), m_code(0) {}
  };

  static std::unique_ptr<AsyncFileSystemCallbacks> create(
      CreateFileResult* result,
      const String& name,
      const KURL& url,
      FileSystemType type) {
    return wrapUnique(static_cast<AsyncFileSystemCallbacks*>(
        new CreateFileHelper(result, name, url, type)));
  }

  void didFail(int code) override {
    m_result->m_failed = true;
    m_result->m_code = code;
  }

  ~CreateFileHelper() override {}

  void didCreateSnapshotFile(const FileMetadata& metadata,
                             PassRefPtr<BlobDataHandle> snapshot) override {
    // We can't directly use the snapshot blob data handle because the content
    // type on it hasn't been set.  The |snapshot| param is here to provide a a
    // chain of custody thru thread bridging that is held onto until *after*
    // we've coined a File with a new handle that has the correct type set on
    // it. This allows the blob storage system to track when a temp file can and
    // can't be safely deleted.

    m_result->m_file =
        DOMFileSystemBase::createFile(metadata, m_url, m_type, m_name);
  }

  bool shouldBlockUntilCompletion() const override { return true; }

 private:
  CreateFileHelper(CreateFileResult* result,
                   const String& name,
                   const KURL& url,
                   FileSystemType type)
      : m_result(result), m_name(name), m_url(url), m_type(type) {}

  Persistent<CreateFileResult> m_result;
  String m_name;
  KURL m_url;
  FileSystemType m_type;
};

}  // namespace

File* DOMFileSystemSync::createFile(const FileEntrySync* fileEntry,
                                    ExceptionState& exceptionState) {
  KURL fileSystemURL = createFileSystemURL(fileEntry);
  CreateFileHelper::CreateFileResult* result(
      CreateFileHelper::CreateFileResult::create());
  fileSystem()->createSnapshotFileAndReadMetadata(
      fileSystemURL, CreateFileHelper::create(result, fileEntry->name(),
                                              fileSystemURL, type()));
  if (result->m_failed) {
    exceptionState.throwDOMException(
        result->m_code, "Could not create '" + fileEntry->name() + "'.");
    return nullptr;
  }
  return result->m_file.get();
}

namespace {

class ReceiveFileWriterCallback final : public FileWriterBaseCallback {
 public:
  static ReceiveFileWriterCallback* create() {
    return new ReceiveFileWriterCallback();
  }

  void handleEvent(FileWriterBase*) override {}

 private:
  ReceiveFileWriterCallback() {}
};

class LocalErrorCallback final : public ErrorCallbackBase {
 public:
  static LocalErrorCallback* create(FileError::ErrorCode& errorCode) {
    return new LocalErrorCallback(errorCode);
  }

  void invoke(FileError::ErrorCode error) override {
    DCHECK_NE(error, FileError::kOK);
    m_errorCode = error;
  }

 private:
  explicit LocalErrorCallback(FileError::ErrorCode& errorCode)
      : m_errorCode(errorCode) {}

  FileError::ErrorCode& m_errorCode;
};

}  // namespace

FileWriterSync* DOMFileSystemSync::createWriter(
    const FileEntrySync* fileEntry,
    ExceptionState& exceptionState) {
  ASSERT(fileEntry);

  FileWriterSync* fileWriter = FileWriterSync::create();
  ReceiveFileWriterCallback* successCallback =
      ReceiveFileWriterCallback::create();
  FileError::ErrorCode errorCode = FileError::kOK;
  LocalErrorCallback* errorCallback = LocalErrorCallback::create(errorCode);

  std::unique_ptr<AsyncFileSystemCallbacks> callbacks =
      FileWriterBaseCallbacks::create(fileWriter, successCallback,
                                      errorCallback, m_context);
  callbacks->setShouldBlockUntilCompletion(true);

  fileSystem()->createFileWriter(createFileSystemURL(fileEntry), fileWriter,
                                 std::move(callbacks));
  if (errorCode != FileError::kOK) {
    FileError::throwDOMException(exceptionState, errorCode);
    return 0;
  }
  return fileWriter;
}

DEFINE_TRACE(DOMFileSystemSync) {
  DOMFileSystemBase::trace(visitor);
  visitor->trace(m_rootEntry);
}

}  // namespace blink
