// 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 "chrome/browser/upgrade_detector.h"

#include "base/bind.h"
#include "base/command_line.h"
#include "chrome/app/vector_icons/vector_icons.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/ui/browser_otr_state.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "components/prefs/pref_registry_simple.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/paint_vector_icon.h"

// How long to wait between checks for whether the user has been idle.
static const int kIdleRepeatingTimerWait = 10;  // Minutes (seconds if testing).

// How much idle time (since last input even was detected) must have passed
// until we notify that a critical update has occurred.
static const int kIdleAmount = 2;  // Hours (or seconds, if testing).

bool UseTestingIntervals() {
  // If a command line parameter specifying how long the upgrade check should
  // be, we assume it is for testing and switch to using seconds instead of
  // hours.
  const base::CommandLine& cmd_line = *base::CommandLine::ForCurrentProcess();
  return !cmd_line.GetSwitchValueASCII(
      switches::kCheckForUpdateIntervalSec).empty();
}

// static
void UpgradeDetector::RegisterPrefs(PrefRegistrySimple* registry) {
  registry->RegisterBooleanPref(prefs::kAttemptedToEnableAutoupdate, false);
}

gfx::Image UpgradeDetector::GetIcon() {
  SkColor color = gfx::kPlaceholderColor;
  switch (upgrade_notification_stage_) {
    case UPGRADE_ANNOYANCE_NONE:
      return gfx::Image();
    case UPGRADE_ANNOYANCE_LOW:
      color = gfx::kGoogleGreen700;
      break;
    case UPGRADE_ANNOYANCE_ELEVATED:
      color = gfx::kGoogleYellow700;
      break;
    case UPGRADE_ANNOYANCE_HIGH:
    case UPGRADE_ANNOYANCE_SEVERE:
    case UPGRADE_ANNOYANCE_CRITICAL:
      color = gfx::kGoogleRed700;
      break;
  }
  DCHECK_NE(gfx::kPlaceholderColor, color);

  return gfx::Image(gfx::CreateVectorIcon(kBrowserToolsUpdateIcon, color));
}

UpgradeDetector::UpgradeDetector()
    : upgrade_available_(UPGRADE_AVAILABLE_NONE),
      best_effort_experiment_updates_available_(false),
      critical_experiment_updates_available_(false),
      critical_update_acknowledged_(false),
      is_factory_reset_required_(false),
      upgrade_notification_stage_(UPGRADE_ANNOYANCE_NONE),
      notify_upgrade_(false) {
}

UpgradeDetector::~UpgradeDetector() {
}

void UpgradeDetector::NotifyOutdatedInstall() {
  for (auto& observer : observer_list_)
    observer.OnOutdatedInstall();
}

void UpgradeDetector::NotifyOutdatedInstallNoAutoUpdate() {
  for (auto& observer : observer_list_)
    observer.OnOutdatedInstallNoAutoUpdate();
}

void UpgradeDetector::NotifyUpgrade() {
  notify_upgrade_ = true;

  NotifyUpgradeRecommended();
  if (upgrade_available_ == UPGRADE_NEEDED_OUTDATED_INSTALL) {
    NotifyOutdatedInstall();
  } else if (upgrade_available_ == UPGRADE_NEEDED_OUTDATED_INSTALL_NO_AU) {
    NotifyOutdatedInstallNoAutoUpdate();
  } else if (upgrade_available_ == UPGRADE_AVAILABLE_CRITICAL ||
             critical_experiment_updates_available_) {
    TriggerCriticalUpdate();
  }
}

void UpgradeDetector::NotifyUpgradeRecommended() {
  for (auto& observer : observer_list_)
    observer.OnUpgradeRecommended();
}

void UpgradeDetector::NotifyCriticalUpgradeInstalled() {
  for (auto& observer : observer_list_)
    observer.OnCriticalUpgradeInstalled();
}

void UpgradeDetector::NotifyUpdateOverCellularAvailable() {
  for (auto& observer : observer_list_)
    observer.OnUpdateOverCellularAvailable();
}

void UpgradeDetector::NotifyUpdateOverCellularOneTimePermissionGranted() {
  for (auto& observer : observer_list_)
    observer.OnUpdateOverCellularOneTimePermissionGranted();
}

void UpgradeDetector::TriggerCriticalUpdate() {
  const base::TimeDelta idle_timer = UseTestingIntervals() ?
      base::TimeDelta::FromSeconds(kIdleRepeatingTimerWait) :
      base::TimeDelta::FromMinutes(kIdleRepeatingTimerWait);
  idle_check_timer_.Start(FROM_HERE, idle_timer, this,
                          &UpgradeDetector::CheckIdle);
}

void UpgradeDetector::CheckIdle() {
  // CalculateIdleState expects an interval in seconds.
  int idle_time_allowed = UseTestingIntervals() ? kIdleAmount :
                                                  kIdleAmount * 60 * 60;

  CalculateIdleState(
      idle_time_allowed, base::Bind(&UpgradeDetector::IdleCallback,
                                    base::Unretained(this)));
}

void UpgradeDetector::IdleCallback(ui::IdleState state) {
  // Don't proceed while an incognito window is open. The timer will still
  // keep firing, so this function will get a chance to re-evaluate this.
  if (chrome::IsIncognitoSessionActive())
    return;

  switch (state) {
    case ui::IDLE_STATE_LOCKED:
      // Computer is locked, auto-restart.
      idle_check_timer_.Stop();
      chrome::AttemptRestart();
      break;
    case ui::IDLE_STATE_IDLE:
      // Computer has been idle for long enough, show warning.
      idle_check_timer_.Stop();
      NotifyCriticalUpgradeInstalled();
      break;
    case ui::IDLE_STATE_ACTIVE:
    case ui::IDLE_STATE_UNKNOWN:
      break;
    default:
      NOTREACHED();  // Need to add any new value above (either providing
                     // automatic restart or show notification to user).
      break;
  }
}

void UpgradeDetector::AddObserver(UpgradeObserver* observer) {
  observer_list_.AddObserver(observer);
}

void UpgradeDetector::RemoveObserver(UpgradeObserver* observer) {
  observer_list_.RemoveObserver(observer);
}
