// Copyright 2018 The Chromium OS 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 "modemfwd/journal.h"

#include <utility>
#include <vector>

#include <base/files/file.h>
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>
#include <brillo/proto_file_io.h>
#include <chromeos/switches/modemfwd_switches.h>

#include "modemfwd/firmware_file.h"
#include "modemfwd/logging.h"
#include "modemfwd/modem_helper.h"
#include "modemfwd/proto_bindings/journal_entry.pb.h"

namespace modemfwd {

namespace {

std::string JournalTypeToFirmwareType(int t) {
  switch (t) {
    case JournalEntryType::MAIN:
      return modemfwd::kFwMain;
    case JournalEntryType::CARRIER:
      return modemfwd::kFwCarrier;
    case JournalEntryType::OEM:
      return modemfwd::kFwOem;
    default:
      return std::string();
  }
  NOTREACHED();
}

JournalEntryType FirmwareTypeToJournalType(std::string fw_type) {
  if (fw_type == modemfwd::kFwMain)
    return JournalEntryType::MAIN;
  else if (fw_type == modemfwd::kFwCarrier)
    return JournalEntryType::CARRIER;
  else if (fw_type == modemfwd::kFwOem)
    return JournalEntryType::OEM;
  else
    return JournalEntryType::UNKNOWN;
}

// Returns true if the operation was restarted successfully or false if it
// failed.
bool RestartOperation(const JournalEntry& entry,
                      FirmwareDirectory* firmware_dir,
                      ModemHelperDirectory* helper_dir) {
  ModemHelper* helper = helper_dir->GetHelperForDeviceId(entry.device_id());
  if (!helper) {
    LOG(ERROR) << "Journal contained unfinished operation for device with ID \""
               << entry.device_id()
               << "\" but no helper was found to restart it";
    return false;
  }

  std::string carrier_id(entry.carrier_id());
  FirmwareDirectory::Files res = firmware_dir->FindFirmware(
      entry.device_id(), carrier_id.empty() ? nullptr : &carrier_id);

  std::vector<FirmwareConfig> flashed_fw;
  std::vector<std::string> paths_for_logging;
  // Keep a reference to all temporary uncompressed files.
  std::vector<std::unique_ptr<FirmwareFile>> all_files;
  for (const auto& entry_type : entry.type()) {
    std::string fw_type = JournalTypeToFirmwareType(entry_type);
    FirmwareFileInfo* info = nullptr;
    base::FilePath fw_path;
    std::string fw_version;

    if (fw_type.empty())
      continue;

    switch (entry_type) {
      case JournalEntryType::MAIN:
        info = base::OptionalOrNullptr<FirmwareFileInfo>(res.main_firmware);
        break;
      case JournalEntryType::CARRIER:
        info = base::OptionalOrNullptr<FirmwareFileInfo>(res.carrier_firmware);
        break;
      case JournalEntryType::OEM:
        info = base::OptionalOrNullptr<FirmwareFileInfo>(res.oem_firmware);
        break;
    }

    auto firmware_file = std::make_unique<FirmwareFile>();
    if (info == nullptr || !firmware_file->PrepareFrom(*info)) {
      LOG(ERROR) << "Unfinished \"" << fw_type
                 << "\" firmware flash for device with ID \""
                 << entry.device_id() << "\" but no firmware was found";
      continue;
    }

    flashed_fw.push_back(
        {fw_type, firmware_file->path_on_filesystem(), info->version});
    paths_for_logging.push_back(firmware_file->path_for_logging().value());
    all_files.push_back(std::move(firmware_file));
  }
  if (flashed_fw.size() != entry.type_size() || !flashed_fw.size()) {
    LOG(ERROR) << "Malformed journal entry with invalid types.";
    return false;
  }

  ELOG(INFO) << "Journal reflashing firmwares: "
             << base::JoinString(paths_for_logging, ",");
  return helper->FlashFirmwares(flashed_fw);
}

class JournalImpl : public Journal {
 public:
  explicit JournalImpl(base::File journal_file)
      : journal_file_(std::move(journal_file)) {
    // Clearing the journal prevents it from growing without bound but also
    // ensures that if we crash after this point, we won't try to restart
    // any operations an extra time.
    ClearJournalFile();
  }
  JournalImpl(const JournalImpl&) = delete;
  JournalImpl& operator=(const JournalImpl&) = delete;

  void MarkStartOfFlashingFirmware(
      const std::vector<std::string>& firmware_types,
      const std::string& device_id,
      const std::string& carrier_id) override {
    JournalEntry entry;
    entry.set_device_id(device_id);
    entry.set_carrier_id(carrier_id);
    for (const auto& t : firmware_types)
      entry.add_type(FirmwareTypeToJournalType(t));
    WriteJournalEntry(entry);
  }

  void MarkEndOfFlashingFirmware(const std::string& device_id,
                                 const std::string& carrier_id) override {
    JournalEntry entry;
    if (!ReadJournalEntry(&entry)) {
      LOG(ERROR) << __func__ << ": no journal entry to commit";
      return;
    }
    if (entry.device_id() != device_id || entry.carrier_id() != carrier_id) {
      LOG(ERROR) << __func__ << ": found journal entry, but it didn't match";
      return;
    }
    ClearJournalFile();
  }

 private:
  bool ReadJournalEntry(JournalEntry* entry) {
    if (journal_file_.GetLength() == 0) {
      ELOG(INFO) << "Tried to read from empty journal";
      return false;
    }
    journal_file_.Seek(base::File::FROM_BEGIN, 0);
    return brillo::ReadTextProtobuf(journal_file_.GetPlatformFile(), entry);
  }

  bool WriteJournalEntry(const JournalEntry& entry) {
    if (journal_file_.GetLength() > 0) {
      ELOG(INFO) << "Tried to write to journal with uncommitted entry";
      return false;
    }
    journal_file_.Seek(base::File::FROM_BEGIN, 0);
    return brillo::WriteTextProtobuf(journal_file_.GetPlatformFile(), entry);
  }

  void ClearJournalFile() {
    journal_file_.SetLength(0);
    journal_file_.Seek(base::File::FROM_BEGIN, 0);
    journal_file_.Flush();
  }

  base::File journal_file_;
};

}  // namespace

std::unique_ptr<Journal> OpenJournal(const base::FilePath& journal_path,
                                     FirmwareDirectory* firmware_dir,
                                     ModemHelperDirectory* helper_dir) {
  base::File journal_file(journal_path, base::File::FLAG_OPEN_ALWAYS |
                                            base::File::FLAG_READ |
                                            base::File::FLAG_WRITE);
  if (!journal_file.IsValid()) {
    LOG(ERROR) << "Could not open journal file";
    return nullptr;
  }

  // Restart operations if necessary.
  if (journal_file.GetLength() > 0) {
    JournalEntry last_entry;
    if (brillo::ReadTextProtobuf(journal_file.GetPlatformFile(), &last_entry) &&
        !RestartOperation(last_entry, firmware_dir, helper_dir)) {
      LOG(ERROR) << "Failed to restart uncommitted operation";
    }
  }

  return std::make_unique<JournalImpl>(std::move(journal_file));
}

}  // namespace modemfwd
