// Copyright 2017 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/modem_flasher.h"

#include <memory>
#include <utility>

#include <base/files/file_util.h>
#include <base/stl_util.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>

#include "modemfwd/firmware_file.h"
#include "modemfwd/logging.h"
#include "modemfwd/modem.h"

namespace {

constexpr char kDisableAutoUpdatePref[] =
    "/var/lib/modemfwd/disable_auto_update";

}  // namespace

namespace modemfwd {

bool IsAutoUpdateDisabledByPref() {
  const base::FilePath pref_path(kDisableAutoUpdatePref);
  std::string contents;
  if (!base::ReadFileToString(pref_path, &contents))
    return false;

  contents = base::TrimWhitespaceASCII(contents, base::TRIM_ALL).as_string();
  int pref_value;
  if (!base::StringToInt(contents, &pref_value))
    return false;

  return (pref_value == 1);
}

ModemFlasher::ModemFlasher(
    std::unique_ptr<FirmwareDirectory> firmware_directory,
    std::unique_ptr<Journal> journal)
    : firmware_directory_(std::move(firmware_directory)),
      journal_(std::move(journal)) {}

base::Closure ModemFlasher::TryFlash(Modem* modem) {
  if (IsAutoUpdateDisabledByPref()) {
    LOG(INFO) << "Update disabled by pref";
    return base::Closure();
  }

  std::string equipment_id = modem->GetEquipmentId();
  FlashState* flash_state = &modem_info_[equipment_id];
  if (!flash_state->ShouldFlash()) {
    LOG(WARNING) << "Modem with equipment ID \"" << equipment_id
                 << "\" failed to flash too many times; not flashing";
    return base::Closure();
  }

  std::string device_id = modem->GetDeviceId();
  std::string current_carrier = modem->GetCarrierId();
  flash_state->OnCarrierSeen(current_carrier);
  FirmwareDirectory::Files files = firmware_directory_->FindFirmware(
      device_id, current_carrier.empty() ? nullptr : &current_carrier);

  // Check if we need to update the main firmware.
  if (flash_state->ShouldFlashMainFirmware() &&
      files.main_firmware.has_value()) {
    const FirmwareFileInfo& file_info = files.main_firmware.value();
    ELOG(INFO) << "Found main firmware blob " << file_info.version
               << ", currently installed main firmware version: "
               << modem->GetMainFirmwareVersion();
    if (file_info.version == modem->GetMainFirmwareVersion()) {
      // We don't need to check the main firmware again if there's nothing new.
      // Pretend that we successfully flashed it.
      flash_state->OnFlashedMainFirmware();
    } else {
      FirmwareFile firmware_file;
      if (!firmware_file.PrepareFrom(file_info))
        return base::Closure();

      // We found different firmware! Flash the modem, and since it will
      // reboot afterwards, we can wait to get called again to check the
      // carrier firmware.
      journal_->MarkStartOfFlashingMainFirmware(device_id, current_carrier);
      if (modem->FlashMainFirmware(firmware_file.path_on_filesystem(),
                                   file_info.version)) {
        // Refer to |firmware_file.path_for_logging()| in the log and journal.
        flash_state->OnFlashedMainFirmware();
        ELOG(INFO) << "Flashed " << firmware_file.path_for_logging().value()
                   << " to the modem";
        return base::Bind(&Journal::MarkEndOfFlashingMainFirmware,
                          base::Unretained(journal_.get()), device_id,
                          current_carrier);
      } else {
        flash_state->OnFlashFailed();
        journal_->MarkEndOfFlashingMainFirmware(device_id, current_carrier);
        return base::Closure();
      }
    }
  }

  // If there's no SIM, we can stop here.
  if (current_carrier.empty()) {
    ELOG(INFO) << "No carrier found. Is a SIM card inserted?";
    return base::Closure();
  }

  // Check if we have carrier firmware matching the SIM's carrier. If not,
  // there's nothing to flash.
  if (!files.carrier_firmware.has_value()) {
    ELOG(INFO) << "No carrier firmware found for carrier " << current_carrier;
    return base::Closure();
  }

  const FirmwareFileInfo& file_info = files.carrier_firmware.value();
  if (!flash_state->ShouldFlashCarrierFirmware(file_info.firmware_path)) {
    ELOG(INFO) << "Already flashed carrier firmware for " << current_carrier;
    return base::Closure();
  }

  ELOG(INFO) << "Found carrier firmware blob " << file_info.version
             << " for carrier " << current_carrier;

  // Carrier firmware operates a bit differently. We need to flash if
  // the carrier or the version has changed, or if there wasn't any carrier
  // firmware to begin with.
  std::string carrier_fw_id = modem->GetCarrierFirmwareId();
  std::string carrier_fw_version = modem->GetCarrierFirmwareVersion();
  bool has_carrier_fw = !(carrier_fw_id.empty() || carrier_fw_version.empty());
  if (has_carrier_fw) {
    ELOG(INFO) << "Currently installed carrier firmware version "
               << carrier_fw_version << " for carrier " << carrier_fw_id;
  } else {
    ELOG(INFO) << "No carrier firmware is currently installed";
  }

  if (!has_carrier_fw || carrier_fw_id != current_carrier ||
      carrier_fw_version != file_info.version) {
    FirmwareFile firmware_file;
    if (!firmware_file.PrepareFrom(file_info))
      return base::Closure();

    journal_->MarkStartOfFlashingCarrierFirmware(device_id, current_carrier);
    if (modem->FlashCarrierFirmware(firmware_file.path_on_filesystem(),
                                    file_info.version)) {
      // Refer to |firmware_file.path_for_logging()| in the log and journal.
      flash_state->OnFlashedCarrierFirmware(firmware_file.path_for_logging());
      ELOG(INFO) << "Flashed " << firmware_file.path_for_logging().value()
                 << " to the modem";
      return base::Bind(&Journal::MarkEndOfFlashingCarrierFirmware,
                        base::Unretained(journal_.get()), device_id,
                        current_carrier);
    } else {
      flash_state->OnFlashFailed();
      journal_->MarkEndOfFlashingCarrierFirmware(device_id, current_carrier);
      return base::Closure();
    }
  }

  return base::Closure();
}

}  // namespace modemfwd
