// Copyright (c) 2012 The Chromium 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 "chromeos/network/device_state.h"

#include <memory>

#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
#include "chromeos/network/network_event_log.h"
#include "chromeos/network/shill_property_util.h"
#include "third_party/cros_system_api/dbus/service_constants.h"

namespace chromeos {

DeviceState::DeviceState(const std::string& path)
    : ManagedState(MANAGED_TYPE_DEVICE, path),
      allow_roaming_(false),
      provider_requires_roaming_(false),
      support_network_scan_(false),
      scanning_(false),
      sim_retries_left_(0),
      sim_present_(true),
      eap_authentication_completed_(false) {
}

DeviceState::~DeviceState() = default;

bool DeviceState::PropertyChanged(const std::string& key,
                                  const base::Value& value) {
  // All property values get stored in |properties_|.
  properties_.SetKey(key, value.Clone());

  if (ManagedStatePropertyChanged(key, value))
    return true;
  if (key == shill::kAddressProperty) {
    return GetStringValue(key, value, &mac_address_);
  } else if (key == shill::kScanningProperty) {
    return GetBooleanValue(key, value, &scanning_);
  } else if (key == shill::kSupportNetworkScanProperty) {
    return GetBooleanValue(key, value, &support_network_scan_);
  } else if (key == shill::kCellularAllowRoamingProperty) {
    return GetBooleanValue(key, value, &allow_roaming_);
  } else if (key == shill::kProviderRequiresRoamingProperty) {
    return GetBooleanValue(key, value, &provider_requires_roaming_);
  } else if (key == shill::kHomeProviderProperty) {
    if (!value.is_dict()) {
      operator_name_.clear();
      country_code_.clear();
      return true;
    }
    const base::Value* operator_name = value.FindKey(shill::kOperatorNameKey);
    if (operator_name)
      operator_name_ = operator_name->GetString();
    if (operator_name_.empty()) {
      const base::Value* operator_code = value.FindKey(shill::kOperatorCodeKey);
      operator_name_ = operator_code ? operator_code->GetString() : "";
    }
    const base::Value* country_code = value.FindKey(shill::kOperatorCountryKey);
    country_code_ = country_code ? country_code->GetString() : "";
  } else if (key == shill::kTechnologyFamilyProperty) {
    return GetStringValue(key, value, &technology_family_);
  } else if (key == shill::kCarrierProperty) {
    return GetStringValue(key, value, &carrier_);
  } else if (key == shill::kFoundNetworksProperty) {
    const base::ListValue* list = nullptr;
    if (!value.GetAsList(&list))
      return false;
    CellularScanResults parsed_results;
    if (!network_util::ParseCellularScanResults(*list, &parsed_results))
      return false;
    scan_results_.swap(parsed_results);
    return true;
  } else if (key == shill::kSIMLockStatusProperty) {
    const base::DictionaryValue* dict = nullptr;
    if (!value.GetAsDictionary(&dict))
      return false;

    // Set default values for SIM properties.
    sim_lock_type_.erase();
    sim_retries_left_ = 0;
    sim_lock_enabled_ = false;

    const base::Value* out_value = nullptr;
    if (dict->GetWithoutPathExpansion(shill::kSIMLockTypeProperty,
                                      &out_value)) {
      GetStringValue(shill::kSIMLockTypeProperty, *out_value, &sim_lock_type_);
    }
    if (dict->GetWithoutPathExpansion(shill::kSIMLockRetriesLeftProperty,
                                      &out_value)) {
      GetIntegerValue(shill::kSIMLockRetriesLeftProperty, *out_value,
                      &sim_retries_left_);
    }
    if (dict->GetWithoutPathExpansion(shill::kSIMLockEnabledProperty,
                                      &out_value)) {
      GetBooleanValue(shill::kSIMLockEnabledProperty, *out_value,
                      &sim_lock_enabled_);
    }
    return true;
  } else if (key == shill::kMeidProperty) {
    return GetStringValue(key, value, &meid_);
  } else if (key == shill::kImeiProperty) {
    return GetStringValue(key, value, &imei_);
  } else if (key == shill::kIccidProperty) {
    return GetStringValue(key, value, &iccid_);
  } else if (key == shill::kMdnProperty) {
    return GetStringValue(key, value, &mdn_);
  } else if (key == shill::kSIMPresentProperty) {
    return GetBooleanValue(key, value, &sim_present_);
  } else if (key == shill::kEapAuthenticationCompletedProperty) {
    return GetBooleanValue(key, value, &eap_authentication_completed_);
  } else if (key == shill::kIPConfigsProperty) {
    // If kIPConfigsProperty changes, clear any previous ip_configs_.
    // ShillPropertyhandler will request the IPConfig objects which will trigger
    // calls to IPConfigPropertiesChanged.
    ip_configs_.Clear();
    return false;  // No actual state change.
  }
  return false;
}

void DeviceState::IPConfigPropertiesChanged(const std::string& ip_config_path,
                                            const base::Value& properties) {
  NET_LOG(EVENT) << "IPConfig for: " << path()
                 << " Changed: " << ip_config_path;
  ip_configs_.SetKey(ip_config_path, properties.Clone());
}

std::string DeviceState::GetName() const {
  if (!operator_name_.empty())
    return operator_name_;
  return name();
}

std::string DeviceState::GetIpAddressByType(const std::string& type) const {
  for (base::DictionaryValue::Iterator iter(ip_configs_); !iter.IsAtEnd();
       iter.Advance()) {
    const base::DictionaryValue* ip_config;
    if (!iter.value().GetAsDictionary(&ip_config))
      continue;
    std::string ip_config_method;
    if (!ip_config->GetString(shill::kMethodProperty, &ip_config_method))
      continue;
    if (type == ip_config_method ||
        (type == shill::kTypeIPv4 && ip_config_method == shill::kTypeDHCP) ||
        (type == shill::kTypeIPv6 && ip_config_method == shill::kTypeDHCP6)) {
      std::string address;
      if (!ip_config->GetString(shill::kAddressProperty, &address))
        continue;
      return address;
    }
  }
  return std::string();
}

bool DeviceState::IsSimAbsent() const {
  return technology_family_ != shill::kTechnologyFamilyCdma && !sim_present_;
}

bool DeviceState::IsSimLocked() const {
  if (technology_family_ == shill::kTechnologyFamilyCdma || !sim_present_)
    return false;
  return sim_lock_type_ == shill::kSIMLockPin ||
         sim_lock_type_ == shill::kSIMLockPuk;
}

}  // namespace chromeos
