//
// Copyright (C) 2011 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/omaha_request_params.h"

#include <errno.h>
#include <fcntl.h>
#include <sys/utsname.h>

#include <map>
#include <string>
#include <vector>

#include <base/files/file_util.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <brillo/key_value_store.h>
#include <brillo/strings/string_utils.h>
#include <policy/device_policy.h>

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

#define CALL_MEMBER_FN(object, member) ((object).*(member))

using std::map;
using std::string;
using std::vector;

namespace chromeos_update_engine {

const char OmahaRequestParams::kOsVersion[] = "Indy";

const char* kChannelsByStability[] = {
    // This list has to be sorted from least stable to most stable channel.
    "canary-channel",
    "dev-channel",
    "beta-channel",
    "stable-channel",
};

OmahaRequestParams::~OmahaRequestParams() {
  if (!root_.empty())
    test::SetImagePropertiesRootPrefix(nullptr);
}

bool OmahaRequestParams::Init(const string& in_app_version,
                              const string& in_update_url,
                              bool in_interactive) {
  LOG(INFO) << "Initializing parameters for this update attempt";
  image_props_ = LoadImageProperties(system_state_);
  mutable_image_props_ = LoadMutableImageProperties(system_state_);

  // Sanity check the channel names.
  if (!IsValidChannel(image_props_.current_channel))
    image_props_.current_channel = "stable-channel";
  if (!IsValidChannel(mutable_image_props_.target_channel))
    mutable_image_props_.target_channel = image_props_.current_channel;
  UpdateDownloadChannel();

  LOG(INFO) << "Running from channel " << image_props_.current_channel;

  os_platform_ = constants::kOmahaPlatformName;
  if (!image_props_.system_version.empty())
    os_version_ = image_props_.system_version;
  else
    os_version_ = OmahaRequestParams::kOsVersion;
  if (!in_app_version.empty())
    image_props_.version = in_app_version;

  os_sp_ = image_props_.version + "_" + GetMachineType();
  app_lang_ = "en-US";
  hwid_ = system_state_->hardware()->GetHardwareClass();
  if (CollectECFWVersions()) {
    fw_version_ = system_state_->hardware()->GetFirmwareVersion();
    ec_version_ = system_state_->hardware()->GetECVersion();
  }

  if (image_props_.current_channel == mutable_image_props_.target_channel) {
    // deltas are only okay if the /.nodelta file does not exist.  if we don't
    // know (i.e. stat() returns some unexpected error), then err on the side of
    // caution and say deltas are not okay.
    struct stat stbuf;
    delta_okay_ = (stat((root_ + "/.nodelta").c_str(), &stbuf) < 0) &&
                  (errno == ENOENT);
  } else {
    LOG(INFO) << "Disabling deltas as a channel change to "
              << mutable_image_props_.target_channel
              << " is pending, with is_powerwash_allowed="
              << utils::ToString(mutable_image_props_.is_powerwash_allowed);
    // For now, disable delta updates if the current channel is different from
    // the channel that we're sending to the update server because such updates
    // are destined to fail -- the current rootfs hash will be different than
    // the expected hash due to the different channel in /etc/lsb-release.
    delta_okay_ = false;
  }

  if (in_update_url.empty())
    update_url_ = image_props_.omaha_url;
  else
    update_url_ = in_update_url;

  // Set the interactive flag accordingly.
  interactive_ = in_interactive;
  return true;
}

bool OmahaRequestParams::IsUpdateUrlOfficial() const {
  return (update_url_ == constants::kOmahaDefaultAUTestURL ||
          update_url_ == image_props_.omaha_url);
}

bool OmahaRequestParams::CollectECFWVersions() const {
  return base::StartsWith(hwid_, string("SAMS ALEX"),
                          base::CompareCase::SENSITIVE) ||
         base::StartsWith(hwid_, string("BUTTERFLY"),
                          base::CompareCase::SENSITIVE) ||
         base::StartsWith(hwid_, string("LUMPY"),
                          base::CompareCase::SENSITIVE) ||
         base::StartsWith(hwid_, string("PARROT"),
                          base::CompareCase::SENSITIVE) ||
         base::StartsWith(hwid_, string("SPRING"),
                          base::CompareCase::SENSITIVE) ||
         base::StartsWith(hwid_, string("SNOW"), base::CompareCase::SENSITIVE);
}

bool OmahaRequestParams::SetTargetChannel(const string& new_target_channel,
                                          bool is_powerwash_allowed,
                                          string* error_message) {
  LOG(INFO) << "SetTargetChannel called with " << new_target_channel
            << ", Is Powerwash Allowed = "
            << utils::ToString(is_powerwash_allowed)
            << ". Current channel = " << image_props_.current_channel
            << ", existing target channel = "
            << mutable_image_props_.target_channel
            << ", download channel = " << download_channel_;
  if (!IsValidChannel(new_target_channel)) {
    string valid_channels = brillo::string_utils::JoinRange(
        ", ",
        std::begin(kChannelsByStability),
        std::end(kChannelsByStability));
    if (error_message) {
      *error_message = base::StringPrintf(
          "Invalid channel name \"%s\", valid names are: %s",
          new_target_channel.c_str(), valid_channels.c_str());
    }
    return false;
  }

  MutableImageProperties new_props;
  new_props.target_channel = new_target_channel;
  new_props.is_powerwash_allowed = is_powerwash_allowed;

  if (!StoreMutableImageProperties(system_state_, new_props)) {
    if (error_message)
      *error_message = "Error storing the new channel value.";
    return false;
  }
  mutable_image_props_ = new_props;
  return true;
}

void OmahaRequestParams::UpdateDownloadChannel() {
  if (download_channel_ != mutable_image_props_.target_channel) {
    download_channel_ = mutable_image_props_.target_channel;
    LOG(INFO) << "Download channel for this attempt = " << download_channel_;
  }
}

string OmahaRequestParams::GetMachineType() const {
  struct utsname buf;
  string ret;
  if (uname(&buf) == 0)
    ret = buf.machine;
  return ret;
}

bool OmahaRequestParams::IsValidChannel(const string& channel) const {
  return GetChannelIndex(channel) >= 0;
}

void OmahaRequestParams::set_root(const string& root) {
  root_ = root;
  test::SetImagePropertiesRootPrefix(root_.c_str());
}

int OmahaRequestParams::GetChannelIndex(const string& channel) const {
  for (size_t t = 0; t < arraysize(kChannelsByStability); ++t)
    if (channel == kChannelsByStability[t])
      return t;

  return -1;
}

bool OmahaRequestParams::to_more_stable_channel() const {
  int current_channel_index = GetChannelIndex(image_props_.current_channel);
  int download_channel_index = GetChannelIndex(download_channel_);

  return download_channel_index > current_channel_index;
}

string OmahaRequestParams::GetAppId() const {
  return download_channel_ == "canary-channel" ? image_props_.canary_product_id
                                               : image_props_.product_id;
}

}  // namespace chromeos_update_engine
