// Copyright 2016 The Cobalt Authors. 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 "cobalt/storage/savegame_thread.h"

#include <memory>
#include <utility>

#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/trace_event/trace_event.h"

// An arbitrary max size for the save game file so that, eg, a
// corrupt filesystem cannot cause us to allocate a fatally large
// memory buffer.
static size_t kMaxSaveGameSizeBytes = 4 * 1024 * 1024;

namespace cobalt {
namespace storage {

SavegameThread::SavegameThread(const Savegame::Options& options)
    : options_(options),
      initialized_(base::WaitableEvent::ResetPolicy::MANUAL,
                   base::WaitableEvent::InitialState::NOT_SIGNALED),
      thread_(new base::Thread("Savegame I/O")),
      num_consecutive_flush_failures_(0) {
  TRACE_EVENT0("cobalt::storage", __FUNCTION__);
  thread_->Start();
  thread_->message_loop()->task_runner()->PostTask(
      FROM_HERE, base::Bind(&SavegameThread::InitializeOnIOThread,
                            base::Unretained(this)));
}

SavegameThread::~SavegameThread() {
  TRACE_EVENT0("cobalt::storage", __FUNCTION__);

  if (thread_) {
    // Wait for all previously posted tasks to finish.
    thread_->message_loop()->task_runner()->WaitForFence();
    // This will trigger a call to WillDestroyCurrentMessageLoop in the thread
    // and wait for it to finish.
    thread_.reset();
  }
}

std::unique_ptr<Savegame::ByteVector> SavegameThread::GetLoadedRawBytes() {
  TRACE_EVENT0("cobalt::storage", __FUNCTION__);
  initialized_.Wait();
  return std::move(loaded_raw_bytes_);
}

void SavegameThread::Flush(std::unique_ptr<Savegame::ByteVector> raw_bytes_ptr,
                           const base::Closure& on_flush_complete) {
  TRACE_EVENT0("cobalt::storage", __FUNCTION__);
  DCHECK(raw_bytes_ptr->size() < kMaxSaveGameSizeBytes);
  if (raw_bytes_ptr->size() > kMaxSaveGameSizeBytes) {
    // We must not save a file larger than kMaxSaveGameSizeBytes
    // because we won't be able to reload it. Something must have
    // gone wrong, and it's far better to leave any existing readable
    // data that's persisted than it is to risk making it unreadable.
    if (!on_flush_complete.is_null()) {
      on_flush_complete.Run();
    }
    return;
  }
  thread_->message_loop()->task_runner()->PostTask(
      FROM_HERE,
      base::Bind(&SavegameThread::FlushOnIOThread, base::Unretained(this),
                 base::Passed(&raw_bytes_ptr), on_flush_complete));
}

void SavegameThread::InitializeOnIOThread() {
  TRACE_EVENT0("cobalt::storage", __FUNCTION__);
  DCHECK(thread_->message_loop()->task_runner()->RunsTasksInCurrentSequence());
  base::MessageLoopCurrent::Get()->AddDestructionObserver(this);

  // Create a savegame object on the storage I/O thread.
  savegame_ = options_.CreateSavegame();

  // Load the save data into our VFS, if it exists.
  loaded_raw_bytes_.reset(new Savegame::ByteVector());
  savegame_->Read(loaded_raw_bytes_.get(), kMaxSaveGameSizeBytes);

  // Signal storage is ready. Anyone waiting for the load will now be unblocked.
  initialized_.Signal();
}

void SavegameThread::WillDestroyCurrentMessageLoop() {
  TRACE_EVENT0("cobalt::storage", __FUNCTION__);
  // Ensure these objects are destroyed on the proper thread.
  savegame_.reset();
  loaded_raw_bytes_.reset();
}

void SavegameThread::FlushOnIOThread(
    std::unique_ptr<Savegame::ByteVector> raw_bytes_ptr,
    const base::Closure& on_flush_complete) {
  TRACE_EVENT0("cobalt::storage", __FUNCTION__);
  DCHECK(thread_->message_loop()->task_runner()->RunsTasksInCurrentSequence());
  if (raw_bytes_ptr->size() > 0) {
    bool ret = savegame_->Write(*raw_bytes_ptr);
    if (ret) {
      num_consecutive_flush_failures_ = 0;
    } else {
      DLOG(ERROR) << "Save failed.";
      const int kMaxConsecutiveFlushFailures = 2;
      DCHECK_LT(++num_consecutive_flush_failures_,
                kMaxConsecutiveFlushFailures);
    }
  }

  if (!on_flush_complete.is_null()) {
    on_flush_complete.Run();
  }
}

}  // namespace storage
}  // namespace cobalt
