//
// Copyright (C) 2015 The Android Open Source Project
//
// 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 "update_engine/image_properties.h"

#include <string>
#include <vector>

#include <base/files/file_util.h>
#include <base/logging.h>
#include <brillo/key_value_store.h>

#include "update_engine/common/constants.h"
#include "update_engine/common/hardware_interface.h"
#include "update_engine/common/platform_constants.h"
#include "update_engine/system_state.h"

namespace {

const char kLsbRelease[] = "/etc/lsb-release";

const char kLsbReleaseAppIdKey[] = "CHROMEOS_RELEASE_APPID";
const char kLsbReleaseAutoUpdateServerKey[] = "CHROMEOS_AUSERVER";
const char kLsbReleaseBoardAppIdKey[] = "CHROMEOS_BOARD_APPID";
const char kLsbReleaseBoardKey[] = "CHROMEOS_RELEASE_BOARD";
const char kLsbReleaseCanaryAppIdKey[] = "CHROMEOS_CANARY_APPID";
const char kLsbReleaseIsPowerwashAllowedKey[] = "CHROMEOS_IS_POWERWASH_ALLOWED";
const char kLsbReleaseUpdateChannelKey[] = "CHROMEOS_RELEASE_TRACK";
const char kLsbReleaseVersionKey[] = "CHROMEOS_RELEASE_VERSION";

const char kDefaultAppId[] = "{87efface-864d-49a5-9bb3-4b050a7c227a}";

// A prefix added to the path, used for testing.
const char* root_prefix = nullptr;

std::string GetStringWithDefault(const brillo::KeyValueStore& store,
                                 const std::string& key,
                                 const std::string& default_value) {
  std::string result;
  if (store.GetString(key, &result))
    return result;
  LOG(INFO) << "Cannot load ImageProperty " << key << ", using default value "
            << default_value;
  return default_value;
}

enum class LsbReleaseSource {
  kSystem,
  kStateful,
};

// Loads the lsb-release properties into the key-value |store| reading the file
// from either the system image or the stateful partition as specified by
// |source|. The loaded values are added to the store, possibly overriding
// existing values.
void LoadLsbRelease(LsbReleaseSource source, brillo::KeyValueStore* store) {
  std::string path;
  if (root_prefix)
    path = root_prefix;
  if (source == LsbReleaseSource::kStateful)
    path += chromeos_update_engine::kStatefulPartition;
  store->Load(base::FilePath(path + kLsbRelease));
}

}  // namespace

namespace chromeos_update_engine {

namespace test {
void SetImagePropertiesRootPrefix(const char* test_root_prefix) {
  root_prefix = test_root_prefix;
}
}  // namespace test

ImageProperties LoadImageProperties(SystemState* system_state) {
  ImageProperties result;

  brillo::KeyValueStore lsb_release;
  LoadLsbRelease(LsbReleaseSource::kSystem, &lsb_release);
  result.current_channel = GetStringWithDefault(
      lsb_release, kLsbReleaseUpdateChannelKey, "stable-channel");

  // In dev-mode and unofficial build we can override the image properties set
  // in the system image with the ones from the stateful partition, except the
  // channel of the current image.
  HardwareInterface* const hardware = system_state->hardware();
  if (!hardware->IsOfficialBuild() || !hardware->IsNormalBootMode())
    LoadLsbRelease(LsbReleaseSource::kStateful, &lsb_release);

  // The release_app_id is used as the default appid, but can be override by
  // the board appid in the general case or the canary appid for the canary
  // channel only.
  std::string release_app_id =
      GetStringWithDefault(lsb_release, kLsbReleaseAppIdKey, kDefaultAppId);

  result.product_id = GetStringWithDefault(
      lsb_release, kLsbReleaseBoardAppIdKey, release_app_id);
  result.canary_product_id = GetStringWithDefault(
      lsb_release, kLsbReleaseCanaryAppIdKey, release_app_id);
  result.board = GetStringWithDefault(lsb_release, kLsbReleaseBoardKey, "");
  result.version = GetStringWithDefault(lsb_release, kLsbReleaseVersionKey, "");
  result.omaha_url =
      GetStringWithDefault(lsb_release, kLsbReleaseAutoUpdateServerKey,
                           constants::kOmahaDefaultProductionURL);
  // Build fingerprint not used in Chrome OS.
  result.buiild_fingerprint = "";

  return result;
}

MutableImageProperties LoadMutableImageProperties(SystemState* system_state) {
  MutableImageProperties result;
  brillo::KeyValueStore lsb_release;
  LoadLsbRelease(LsbReleaseSource::kSystem, &lsb_release);
  LoadLsbRelease(LsbReleaseSource::kStateful, &lsb_release);
  result.target_channel = GetStringWithDefault(
      lsb_release, kLsbReleaseUpdateChannelKey, "stable-channel");
  if (!lsb_release.GetBoolean(kLsbReleaseIsPowerwashAllowedKey,
                              &result.is_powerwash_allowed))
    result.is_powerwash_allowed = false;
  return result;
}

bool StoreMutableImageProperties(SystemState* system_state,
                                 const MutableImageProperties& properties) {
  brillo::KeyValueStore lsb_release;
  LoadLsbRelease(LsbReleaseSource::kStateful, &lsb_release);
  lsb_release.SetString(kLsbReleaseUpdateChannelKey, properties.target_channel);
  lsb_release.SetBoolean(kLsbReleaseIsPowerwashAllowedKey,
                         properties.is_powerwash_allowed);

  std::string root_prefix_str = root_prefix ? root_prefix : "";
  base::FilePath path(root_prefix_str + kStatefulPartition + kLsbRelease);
  if (!base::DirectoryExists(path.DirName()))
    base::CreateDirectory(path.DirName());
  return lsb_release.Save(path);
}

}  // namespace chromeos_update_engine
