// Copyright 2014 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/signin/easy_unlock_screenlock_state_handler.h"

#include "base/bind.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/chromeos_utils.h"
#include "chrome/grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"

namespace {

ScreenlockBridge::UserPodCustomIcon GetIconForState(
    EasyUnlockScreenlockStateHandler::State state) {
  switch (state) {
    case EasyUnlockScreenlockStateHandler::STATE_NO_BLUETOOTH:
    case EasyUnlockScreenlockStateHandler::STATE_NO_PHONE:
    case EasyUnlockScreenlockStateHandler::STATE_PHONE_NOT_AUTHENTICATED:
    case EasyUnlockScreenlockStateHandler::STATE_PHONE_LOCKED:
    case EasyUnlockScreenlockStateHandler::STATE_PHONE_NOT_NEARBY:
    case EasyUnlockScreenlockStateHandler::STATE_PHONE_UNLOCKABLE:
    case EasyUnlockScreenlockStateHandler::STATE_PHONE_UNSUPPORTED:
      return ScreenlockBridge::USER_POD_CUSTOM_ICON_LOCKED;
    case EasyUnlockScreenlockStateHandler::STATE_BLUETOOTH_CONNECTING:
      return ScreenlockBridge::USER_POD_CUSTOM_ICON_SPINNER;
    case EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED:
      return ScreenlockBridge::USER_POD_CUSTOM_ICON_UNLOCKED;
    default:
      return ScreenlockBridge::USER_POD_CUSTOM_ICON_NONE;
  }
}

bool HardlockOnClick(EasyUnlockScreenlockStateHandler::State state) {
  return state != EasyUnlockScreenlockStateHandler::STATE_INACTIVE;
}

size_t GetTooltipResourceId(EasyUnlockScreenlockStateHandler::State state) {
  switch (state) {
    case EasyUnlockScreenlockStateHandler::STATE_NO_BLUETOOTH:
      return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_NO_BLUETOOTH;
    case EasyUnlockScreenlockStateHandler::STATE_NO_PHONE:
      return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_NO_PHONE;
    case EasyUnlockScreenlockStateHandler::STATE_PHONE_NOT_AUTHENTICATED:
      return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_PHONE_NOT_AUTHENTICATED;
    case EasyUnlockScreenlockStateHandler::STATE_PHONE_LOCKED:
      return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_PHONE_LOCKED;
    case EasyUnlockScreenlockStateHandler::STATE_PHONE_UNLOCKABLE:
      return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_PHONE_UNLOCKABLE;
    case EasyUnlockScreenlockStateHandler::STATE_PHONE_NOT_NEARBY:
      return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_PHONE_NOT_NEARBY;
    case EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED:
      return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_HARDLOCK_INSTRUCTIONS;
    case EasyUnlockScreenlockStateHandler::STATE_PHONE_UNSUPPORTED:
      return IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_UNSUPPORTED_ANDROID_VERSION;
    default:
      return 0;
  }
}

bool TooltipContainsDeviceType(EasyUnlockScreenlockStateHandler::State state) {
  return state == EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED ||
         state == EasyUnlockScreenlockStateHandler::STATE_PHONE_UNLOCKABLE ||
         state == EasyUnlockScreenlockStateHandler::STATE_NO_BLUETOOTH ||
         state == EasyUnlockScreenlockStateHandler::STATE_PHONE_UNSUPPORTED;
}

bool IsLocaleEnUS() {
  return g_browser_process->GetApplicationLocale() == "en-US";
}

}  // namespace


EasyUnlockScreenlockStateHandler::EasyUnlockScreenlockStateHandler(
    const std::string& user_email,
    HardlockState initial_hardlock_state,
    ScreenlockBridge* screenlock_bridge)
    : state_(STATE_INACTIVE),
      user_email_(user_email),
      screenlock_bridge_(screenlock_bridge),
      hardlock_state_(initial_hardlock_state),
      hardlock_ui_shown_(false),
      is_trial_run_(false) {
  DCHECK(screenlock_bridge_);
  screenlock_bridge_->AddObserver(this);
}

EasyUnlockScreenlockStateHandler::~EasyUnlockScreenlockStateHandler() {
  screenlock_bridge_->RemoveObserver(this);
  // Make sure the screenlock state set by this gets cleared.
  ChangeState(STATE_INACTIVE);
}

bool EasyUnlockScreenlockStateHandler::IsActive() const {
  return state_ != STATE_INACTIVE;
}

void EasyUnlockScreenlockStateHandler::ChangeState(State new_state) {
  if (state_ == new_state)
    return;

  state_ = new_state;

  // If lock screen is not active or it forces offline password, just cache the
  // current state. The screenlock state will get refreshed in |ScreenDidLock|.
  if (!screenlock_bridge_->IsLocked())
    return;

  // No hardlock UI for trial run.
  if (!is_trial_run_ && hardlock_state_ != NO_HARDLOCK) {
    ShowHardlockUI();
    return;
  }

  UpdateScreenlockAuthType();

  ScreenlockBridge::UserPodCustomIcon icon = GetIconForState(state_);

  if (icon == ScreenlockBridge::USER_POD_CUSTOM_ICON_NONE) {
    screenlock_bridge_->lock_handler()->HideUserPodCustomIcon(user_email_);
    return;
  }

  ScreenlockBridge::UserPodCustomIconOptions icon_options;
  icon_options.SetIcon(icon);

  // Don't hardlock on trial run.
  if (!is_trial_run_ && HardlockOnClick(state_))
    icon_options.SetHardlockOnClick();

  UpdateTooltipOptions(is_trial_run_, &icon_options);

  // For states without tooltips, we still need to set an accessibility label.
  if (state_ == EasyUnlockScreenlockStateHandler::STATE_BLUETOOTH_CONNECTING) {
    icon_options.SetAriaLabel(
        l10n_util::GetStringUTF16(IDS_SMART_LOCK_SPINNER_ACCESSIBILITY_LABEL));
  }

  screenlock_bridge_->lock_handler()->ShowUserPodCustomIcon(user_email_,
                                                            icon_options);
}

void EasyUnlockScreenlockStateHandler::SetHardlockState(
    HardlockState new_state) {
  if (hardlock_state_ == new_state)
    return;

  hardlock_state_ = new_state;

  // If hardlock_state_ was set to NO_HARDLOCK, this means the screen is about
  // to get unlocked. No need to update it in this case.
  if (hardlock_state_ != NO_HARDLOCK) {
    hardlock_ui_shown_ = false;

    RefreshScreenlockState();
  }
}

void EasyUnlockScreenlockStateHandler::MaybeShowHardlockUI() {
  if (hardlock_state_ != NO_HARDLOCK)
    ShowHardlockUI();
}

void EasyUnlockScreenlockStateHandler::SetTrialRun() {
  if (is_trial_run_)
    return;
  is_trial_run_ = true;
  RefreshScreenlockState();
}

void EasyUnlockScreenlockStateHandler::OnScreenDidLock() {
  RefreshScreenlockState();
}

void EasyUnlockScreenlockStateHandler::OnScreenDidUnlock() {
  hardlock_ui_shown_ = false;
  is_trial_run_ = false;
}

void EasyUnlockScreenlockStateHandler::OnFocusedUserChanged(
    const std::string& user_id) {
}

void EasyUnlockScreenlockStateHandler::RefreshScreenlockState() {
  State last_state = state_;
  // This should force updating screenlock state.
  state_ = STATE_INACTIVE;
  ChangeState(last_state);
}

void EasyUnlockScreenlockStateHandler::ShowHardlockUI() {
  DCHECK(hardlock_state_ != NO_HARDLOCK);

  if (!screenlock_bridge_->IsLocked())
    return;

  // Do not override online signin.
  const ScreenlockBridge::LockHandler::AuthType existing_auth_type =
      screenlock_bridge_->lock_handler()->GetAuthType(user_email_);
  if (existing_auth_type == ScreenlockBridge::LockHandler::ONLINE_SIGN_IN)
    return;

  if (existing_auth_type != ScreenlockBridge::LockHandler::OFFLINE_PASSWORD) {
    screenlock_bridge_->lock_handler()->SetAuthType(
        user_email_,
        ScreenlockBridge::LockHandler::OFFLINE_PASSWORD,
        base::string16());
  }

  if (hardlock_state_ == NO_PAIRING) {
    screenlock_bridge_->lock_handler()->HideUserPodCustomIcon(user_email_);
    hardlock_ui_shown_ = false;
    return;
  }

  if (hardlock_ui_shown_)
    return;

  ScreenlockBridge::UserPodCustomIconOptions icon_options;
  icon_options.SetIcon(ScreenlockBridge::USER_POD_CUSTOM_ICON_HARDLOCKED);

  // TODO(tbarzic): Remove this condition for M-40.
  if (IsLocaleEnUS()) {
    base::string16 tooltip;
    if (hardlock_state_ == USER_HARDLOCK) {
      tooltip = l10n_util::GetStringFUTF16(
          IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_HARDLOCK_USER, GetDeviceName());
    } else if (hardlock_state_ == PAIRING_CHANGED) {
      tooltip = l10n_util::GetStringUTF16(
          IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_HARDLOCK_PAIRING_CHANGED);
    } else if (hardlock_state_ == PAIRING_ADDED) {
      tooltip = l10n_util::GetStringUTF16(
          IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_HARDLOCK_PAIRING_ADDED);
    } else {
      LOG(ERROR) << "Unknown hardlock state " << hardlock_state_;
    }
    icon_options.SetTooltip(tooltip, true /* autoshow */);
  }

  screenlock_bridge_->lock_handler()->ShowUserPodCustomIcon(user_email_,
                                                            icon_options);
  hardlock_ui_shown_ = true;
}

void EasyUnlockScreenlockStateHandler::UpdateTooltipOptions(
    bool trial_run,
    ScreenlockBridge::UserPodCustomIconOptions* icon_options) {
  size_t resource_id = 0;
  base::string16 device_name;
  if (trial_run && state_ == STATE_AUTHENTICATED) {
    // TODO(tbarzic): Remove this condition for M-40 branch.
    if (IsLocaleEnUS())
      resource_id = IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_INITIAL_AUTHENTICATED;
    else
      resource_id = IDS_EASY_UNLOCK_SCREENLOCK_TOOLTIP_TUTORIAL;
  } else {
    resource_id = GetTooltipResourceId(state_);
    if (TooltipContainsDeviceType(state_))
      device_name = GetDeviceName();
  }

  if (!resource_id)
    return;

  base::string16 tooltip;
  if (device_name.empty()) {
    tooltip = l10n_util::GetStringUTF16(resource_id);
  } else {
    tooltip = l10n_util::GetStringFUTF16(resource_id, device_name);
  }

  if (tooltip.empty())
    return;

  icon_options->SetTooltip(tooltip, trial_run /* autoshow tooltip */);
}

base::string16 EasyUnlockScreenlockStateHandler::GetDeviceName() {
#if defined(OS_CHROMEOS)
  return chromeos::GetChromeDeviceType();
#else
  // TODO(tbarzic): Figure out the name for non Chrome OS case.
  return base::ASCIIToUTF16("Chrome");
#endif
}

void EasyUnlockScreenlockStateHandler::UpdateScreenlockAuthType() {
  if (!is_trial_run_ && hardlock_state_ != NO_HARDLOCK)
    return;

  // Do not override online signin.
  const ScreenlockBridge::LockHandler::AuthType existing_auth_type =
      screenlock_bridge_->lock_handler()->GetAuthType(user_email_);
  if (existing_auth_type == ScreenlockBridge::LockHandler::ONLINE_SIGN_IN)
    return;

  if (state_ == STATE_AUTHENTICATED) {
    if (existing_auth_type != ScreenlockBridge::LockHandler::USER_CLICK) {
      screenlock_bridge_->lock_handler()->SetAuthType(
          user_email_,
          ScreenlockBridge::LockHandler::USER_CLICK,
          l10n_util::GetStringUTF16(
              IDS_EASY_UNLOCK_SCREENLOCK_USER_POD_AUTH_VALUE));
    }
  } else if (existing_auth_type !=
             ScreenlockBridge::LockHandler::OFFLINE_PASSWORD) {
    screenlock_bridge_->lock_handler()->SetAuthType(
        user_email_,
        ScreenlockBridge::LockHandler::OFFLINE_PASSWORD,
        base::string16());
  }
}
