// 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 "base/system_monitor/system_monitor.h"

#include <utility>

#include "base/logging.h"
#include "base/message_loop.h"
#include "base/stl_util.h"
#include "base/time.h"
#include "base/utf_string_conversions.h"

namespace base {

static SystemMonitor* g_system_monitor = NULL;

#if defined(ENABLE_BATTERY_MONITORING)
// The amount of time (in ms) to wait before running the initial
// battery check.
static int kDelayedBatteryCheckMs = 10 * 1000;
#endif  // defined(ENABLE_BATTERY_MONITORING)

SystemMonitor::RemovableStorageInfo::RemovableStorageInfo() {
}

SystemMonitor::RemovableStorageInfo::RemovableStorageInfo(
    const std::string& id,
    const string16& device_name,
    const FilePath::StringType& device_location)
    : device_id(id),
      name(device_name),
      location(device_location) {
}

SystemMonitor::SystemMonitor()
    : power_observer_list_(new ObserverListThreadSafe<PowerObserver>()),
      devices_changed_observer_list_(
          new ObserverListThreadSafe<DevicesChangedObserver>()),
      battery_in_use_(false),
      suspended_(false) {
  DCHECK(!g_system_monitor);
  g_system_monitor = this;

  DCHECK(MessageLoop::current());
#if defined(ENABLE_BATTERY_MONITORING)
  delayed_battery_check_.Start(FROM_HERE,
      base::TimeDelta::FromMilliseconds(kDelayedBatteryCheckMs), this,
      &SystemMonitor::BatteryCheck);
#endif  // defined(ENABLE_BATTERY_MONITORING)
#if defined(OS_MACOSX)
  PlatformInit();
#endif
}

SystemMonitor::~SystemMonitor() {
#if defined(OS_MACOSX)
  PlatformDestroy();
#endif
  DCHECK_EQ(this, g_system_monitor);
  g_system_monitor = NULL;
}

// static
SystemMonitor* SystemMonitor::Get() {
  return g_system_monitor;
}

void SystemMonitor::ProcessPowerMessage(PowerEvent event_id) {
  // Suppress duplicate notifications.  Some platforms may
  // send multiple notifications of the same event.
  switch (event_id) {
    case POWER_STATE_EVENT:
#if !defined(__LB_SHELL__) && !defined(OS_STARBOARD)
      {
        bool on_battery = IsBatteryPower();
        if (on_battery != battery_in_use_) {
          battery_in_use_ = on_battery;
          NotifyPowerStateChange();
        }
      }
#endif
      break;
    case RESUME_EVENT:
      if (suspended_) {
        suspended_ = false;
        NotifyResume();
      }
      break;
    case SUSPEND_EVENT:
      if (!suspended_) {
        suspended_ = true;
        NotifySuspend();
      }
      break;
  }
}

void SystemMonitor::ProcessDevicesChanged(DeviceType device_type) {
  NotifyDevicesChanged(device_type);
}

void SystemMonitor::ProcessRemovableStorageAttached(
    const std::string& id,
    const string16& name,
    const FilePath::StringType& location) {
  {
    base::AutoLock lock(removable_storage_lock_);
    if (ContainsKey(removable_storage_map_, id)) {
      // This can happen if our unique id scheme fails. Ignore the incoming
      // non-unique attachment.
      return;
    }
    RemovableStorageInfo info(id, name, location);
    removable_storage_map_.insert(std::make_pair(id, info));
  }
  NotifyRemovableStorageAttached(id, name, location);
}

void SystemMonitor::ProcessRemovableStorageDetached(const std::string& id) {
  {
    base::AutoLock lock(removable_storage_lock_);
    RemovableStorageMap::iterator it = removable_storage_map_.find(id);
    if (it == removable_storage_map_.end())
      return;
    removable_storage_map_.erase(it);
  }
  NotifyRemovableStorageDetached(id);
}

std::vector<SystemMonitor::RemovableStorageInfo>
SystemMonitor::GetAttachedRemovableStorage() const {
  std::vector<RemovableStorageInfo> results;

  base::AutoLock lock(removable_storage_lock_);
  for (RemovableStorageMap::const_iterator it = removable_storage_map_.begin();
       it != removable_storage_map_.end();
       ++it) {
    results.push_back(it->second);
  }
  return results;
}

void SystemMonitor::AddPowerObserver(PowerObserver* obs) {
  power_observer_list_->AddObserver(obs);
}

void SystemMonitor::RemovePowerObserver(PowerObserver* obs) {
  power_observer_list_->RemoveObserver(obs);
}

void SystemMonitor::AddDevicesChangedObserver(DevicesChangedObserver* obs) {
  devices_changed_observer_list_->AddObserver(obs);
}

void SystemMonitor::RemoveDevicesChangedObserver(DevicesChangedObserver* obs) {
  devices_changed_observer_list_->RemoveObserver(obs);
}

void SystemMonitor::NotifyDevicesChanged(DeviceType device_type) {
  DVLOG(1) << "DevicesChanged with device type " << device_type;
  devices_changed_observer_list_->Notify(
      &DevicesChangedObserver::OnDevicesChanged, device_type);
}

void SystemMonitor::NotifyRemovableStorageAttached(
    const std::string& id,
    const string16& name,
    const FilePath::StringType& location) {
  DVLOG(1) << "RemovableStorageAttached with name " << UTF16ToUTF8(name)
           << " and id " << id;
  devices_changed_observer_list_->Notify(
    &DevicesChangedObserver::OnRemovableStorageAttached, id, name, location);
}

void SystemMonitor::NotifyRemovableStorageDetached(const std::string& id) {
  DVLOG(1) << "RemovableStorageDetached for id " << id;
  devices_changed_observer_list_->Notify(
    &DevicesChangedObserver::OnRemovableStorageDetached, id);
}

void SystemMonitor::NotifyPowerStateChange() {
  DVLOG(1) << "PowerStateChange: " << (BatteryPower() ? "On" : "Off")
           << " battery";
  power_observer_list_->Notify(&PowerObserver::OnPowerStateChange,
                               BatteryPower());
}

void SystemMonitor::NotifySuspend() {
  DVLOG(1) << "Power Suspending";
  power_observer_list_->Notify(&PowerObserver::OnSuspend);
}

void SystemMonitor::NotifyResume() {
  DVLOG(1) << "Power Resuming";
  power_observer_list_->Notify(&PowerObserver::OnResume);
}

void SystemMonitor::BatteryCheck() {
  ProcessPowerMessage(SystemMonitor::POWER_STATE_EVENT);
}

}  // namespace base
