// 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 "ash/system/network/network_state_list_detailed_view.h"

#include <algorithm>

#include "ash/metrics/user_metrics_recorder.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/system/model/system_tray_model.h"
#include "ash/system/tray/system_menu_button.h"
#include "ash/system/tray/tri_view.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "chromeos/network/device_state.h"
#include "chromeos/network/network_connect.h"
#include "chromeos/network/network_state.h"
#include "chromeos/network/network_state_handler.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/views/bubble/bubble_dialog_delegate_view.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/layout/layout_manager.h"
#include "ui/views/widget/widget.h"

using chromeos::DeviceState;
using chromeos::NetworkHandler;
using chromeos::NetworkState;
using chromeos::NetworkStateHandler;
using chromeos::NetworkTypePattern;

namespace ash {
namespace tray {
namespace {

// Delay between scan requests.
constexpr int kRequestScanDelaySeconds = 10;

// This margin value is used throughout the bubble:
// - margins inside the border
// - horizontal spacing between bubble border and parent bubble border
// - distance between top of this bubble's border and the bottom of the anchor
//   view (horizontal rule).
constexpr int kBubbleMargin = 8;

// Elevation used for the bubble shadow effect (tiny).
constexpr int kBubbleShadowElevation = 2;

bool IsSecondaryUser() {
  SessionControllerImpl* session_controller =
      Shell::Get()->session_controller();
  return session_controller->IsActiveUserSessionStarted() &&
         !session_controller->IsUserPrimary();
}

bool IsWifiEnabled() {
  return NetworkHandler::Get()->network_state_handler()->IsTechnologyEnabled(
      chromeos::NetworkTypePattern::WiFi());
}

}  // namespace

// A bubble which displays network info.
class NetworkStateListDetailedView::InfoBubble
    : public views::BubbleDialogDelegateView {
 public:
  InfoBubble(views::View* anchor,
             views::View* content,
             NetworkStateListDetailedView* detailed_view)
      : views::BubbleDialogDelegateView(anchor, views::BubbleBorder::TOP_RIGHT),
        detailed_view_(detailed_view) {
    set_margins(gfx::Insets(kBubbleMargin));
    SetArrow(views::BubbleBorder::NONE);
    set_shadow(views::BubbleBorder::NO_ASSETS);
    set_anchor_view_insets(gfx::Insets(0, 0, kBubbleMargin, 0));
    set_notify_enter_exit_on_child(true);
    SetLayoutManager(std::make_unique<views::FillLayout>());
    AddChildView(content);
  }

  ~InfoBubble() override {
    // The detailed view can be destructed before info bubble is destructed.
    // Call OnInfoBubbleDestroyed only if the detailed view is live.
    if (detailed_view_)
      detailed_view_->OnInfoBubbleDestroyed();
  }

  void OnNetworkStateListDetailedViewIsDeleting() { detailed_view_ = nullptr; }

 private:
  // View:
  gfx::Size CalculatePreferredSize() const override {
    // This bubble should be inset by kBubbleMargin on both left and right
    // relative to the parent bubble.
    const gfx::Size anchor_size = GetAnchorView()->size();
    int contents_width =
        anchor_size.width() - 2 * kBubbleMargin - margins().width();
    return gfx::Size(contents_width, GetHeightForWidth(contents_width));
  }

  void OnMouseExited(const ui::MouseEvent& event) override {
    // Like the user switching bubble/menu, hide the bubble when the mouse
    // exits.
    if (detailed_view_)
      detailed_view_->ResetInfoBubble();
  }

  // BubbleDialogDelegateView:
  int GetDialogButtons() const override { return ui::DIALOG_BUTTON_NONE; }

  void OnBeforeBubbleWidgetInit(views::Widget::InitParams* params,
                                views::Widget* widget) const override {
    params->shadow_type = views::Widget::InitParams::SHADOW_TYPE_DROP;
    params->shadow_elevation = kBubbleShadowElevation;
    params->name = "NetworkStateListDetailedView::InfoBubble";
  }

  // Not owned.
  NetworkStateListDetailedView* detailed_view_;

  DISALLOW_COPY_AND_ASSIGN(InfoBubble);
};

//------------------------------------------------------------------------------

// Special layout to overlap the scanning throbber and the info button.
class InfoThrobberLayout : public views::LayoutManager {
 public:
  InfoThrobberLayout() = default;
  ~InfoThrobberLayout() override = default;

  // views::LayoutManager
  void Layout(views::View* host) override {
    gfx::Size max_size(GetMaxChildSize(host));
    // Center each child view within |max_size|.
    for (auto* child : host->children()) {
      if (!child->visible())
        continue;
      gfx::Size child_size = child->GetPreferredSize();
      gfx::Point origin;
      origin.set_x((max_size.width() - child_size.width()) / 2);
      origin.set_y((max_size.height() - child_size.height()) / 2);
      gfx::Rect bounds(origin, child_size);
      bounds.Inset(-host->GetInsets());
      child->SetBoundsRect(bounds);
    }
  }

  gfx::Size GetPreferredSize(const views::View* host) const override {
    gfx::Point origin;
    gfx::Rect rect(origin, GetMaxChildSize(host));
    rect.Inset(-host->GetInsets());
    return rect.size();
  }

 private:
  gfx::Size GetMaxChildSize(const views::View* host) const {
    gfx::Size max_size;
    for (const auto* child : host->children()) {
      if (child->visible())
        max_size.SetToMax(child->GetPreferredSize());
    }
    return max_size;
  }

  DISALLOW_COPY_AND_ASSIGN(InfoThrobberLayout);
};

//------------------------------------------------------------------------------
// NetworkStateListDetailedView

NetworkStateListDetailedView::NetworkStateListDetailedView(
    DetailedViewDelegate* delegate,
    ListType list_type,
    LoginStatus login)
    : TrayDetailedView(delegate),
      list_type_(list_type),
      login_(login),
      info_button_(nullptr),
      settings_button_(nullptr),
      info_bubble_(nullptr) {}

NetworkStateListDetailedView::~NetworkStateListDetailedView() {
  if (info_bubble_)
    info_bubble_->OnNetworkStateListDetailedViewIsDeleting();
  ResetInfoBubble();
}

void NetworkStateListDetailedView::Update() {
  UpdateNetworkList();
  UpdateHeaderButtons();
  UpdateScanningBar();
  Layout();
}

void NetworkStateListDetailedView::ToggleInfoBubbleForTesting() {
  ToggleInfoBubble();
}

void NetworkStateListDetailedView::Init() {
  CreateScrollableList();
  CreateTitleRow(list_type_ == ListType::LIST_TYPE_NETWORK
                     ? IDS_ASH_STATUS_TRAY_NETWORK
                     : IDS_ASH_STATUS_TRAY_VPN);

  Update();

  if (list_type_ == LIST_TYPE_NETWORK && IsWifiEnabled())
    ScanAndStartTimer();
}

void NetworkStateListDetailedView::HandleButtonPressed(views::Button* sender,
                                                       const ui::Event& event) {
  if (sender == info_button_) {
    ToggleInfoBubble();
    return;
  }

  if (sender == settings_button_)
    ShowSettings();

  CloseBubble();
}

void NetworkStateListDetailedView::HandleViewClicked(views::View* view) {
  if (login_ == LoginStatus::LOCKED)
    return;

  std::string guid;
  if (!IsNetworkEntry(view, &guid))
    return;

  const NetworkState* network =
      NetworkHandler::Get()->network_state_handler()->GetNetworkStateFromGuid(
          guid);
  bool can_connect = network && !network->IsConnectingOrConnected();
  if (network) {
    if (network->IsDefaultCellular())
      can_connect = false;  // Default Cellular network is not connectable.
    if (!network->connectable() && IsSecondaryUser()) {
      // Secondary users can only connect to fully configured networks.
      can_connect = false;
    }
  }
  if (can_connect) {
    Shell::Get()->metrics()->RecordUserMetricsAction(
        list_type_ == LIST_TYPE_VPN
            ? UMA_STATUS_AREA_CONNECT_TO_VPN
            : UMA_STATUS_AREA_CONNECT_TO_CONFIGURED_NETWORK);
    chromeos::NetworkConnect::Get()->ConnectToNetworkId(network->guid());
    return;
  }
  Shell::Get()->metrics()->RecordUserMetricsAction(
      list_type_ == LIST_TYPE_VPN
          ? UMA_STATUS_AREA_SHOW_VPN_CONNECTION_DETAILS
          : UMA_STATUS_AREA_SHOW_NETWORK_CONNECTION_DETAILS);
  Shell::Get()->system_tray_model()->client_ptr()->ShowNetworkSettings(
      network ? network->guid() : std::string());
}

void NetworkStateListDetailedView::CreateExtraTitleRowButtons() {
  if (login_ == LoginStatus::LOCKED)
    return;

  DCHECK(!info_button_);
  tri_view()->SetContainerVisible(TriView::Container::END, true);

  info_button_ = CreateInfoButton(IDS_ASH_STATUS_TRAY_NETWORK_INFO);
  tri_view()->AddView(TriView::Container::END, info_button_);

  DCHECK(!settings_button_);
  settings_button_ = CreateSettingsButton(IDS_ASH_STATUS_TRAY_NETWORK_SETTINGS);
  tri_view()->AddView(TriView::Container::END, settings_button_);
}

void NetworkStateListDetailedView::ShowSettings() {
  Shell::Get()->metrics()->RecordUserMetricsAction(
      list_type_ == LIST_TYPE_VPN ? UMA_STATUS_AREA_VPN_SETTINGS_OPENED
                                  : UMA_STATUS_AREA_NETWORK_SETTINGS_OPENED);
  Shell::Get()->system_tray_model()->client_ptr()->ShowNetworkSettings(
      std::string());
}

void NetworkStateListDetailedView::UpdateHeaderButtons() {
  if (settings_button_) {
    if (login_ == LoginStatus::NOT_LOGGED_IN) {
      // When not logged in, only enable the settings button if there is a
      // default (i.e. connected or connecting) network to show settings for.
      settings_button_->SetEnabled(
          !!NetworkHandler::Get()->network_state_handler()->DefaultNetwork());
    } else {
      // Otherwise, enable if showing settings is allowed. There are situations
      // (supervised user creation flow) when the session is started but UI flow
      // continues within login UI, i.e., no browser window is yet available.
      settings_button_->SetEnabled(
          Shell::Get()->session_controller()->ShouldEnableSettings());
    }
  }
}

void NetworkStateListDetailedView::UpdateScanningBar() {
  if (list_type_ != LIST_TYPE_NETWORK)
    return;

  bool is_wifi_enabled = IsWifiEnabled();
  if (is_wifi_enabled && !network_scan_repeating_timer_.IsRunning())
    ScanAndStartTimer();

  if (!is_wifi_enabled && network_scan_repeating_timer_.IsRunning())
    network_scan_repeating_timer_.Stop();

  const bool scanning_bar_visible =
      is_wifi_enabled &&
      NetworkHandler::Get()->network_state_handler()->GetScanningByType(
          NetworkTypePattern::WiFi() | NetworkTypePattern::Tether());

  ShowProgress(-1, scanning_bar_visible);
}

void NetworkStateListDetailedView::ToggleInfoBubble() {
  if (ResetInfoBubble())
    return;

  info_bubble_ = new InfoBubble(tri_view(), CreateNetworkInfoView(), this);
  views::BubbleDialogDelegateView::CreateBubble(info_bubble_)->Show();
  info_bubble_->NotifyAccessibilityEvent(ax::mojom::Event::kAlert, false);
}

bool NetworkStateListDetailedView::ResetInfoBubble() {
  if (!info_bubble_)
    return false;

  info_bubble_->GetWidget()->Close();
  return true;
}

void NetworkStateListDetailedView::OnInfoBubbleDestroyed() {
  info_bubble_ = nullptr;

  // Widget of info bubble is activated while info bubble is shown. To move
  // focus back to the widget of this view, activate it again here.
  GetWidget()->Activate();
}

views::View* NetworkStateListDetailedView::CreateNetworkInfoView() {
  NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();

  std::string ip_address, ipv6_address;
  const NetworkState* network = handler->DefaultNetwork();
  if (network) {
    ip_address = network->GetIpAddress();
    const DeviceState* device = handler->GetDeviceState(network->device_path());
    if (device)
      ipv6_address = device->GetIpAddressByType(shill::kTypeIPv6);
  }

  std::string ethernet_address, wifi_address;
  if (list_type_ == LIST_TYPE_NETWORK) {
    ethernet_address = handler->FormattedHardwareAddressForType(
        NetworkTypePattern::Ethernet());
    wifi_address =
        handler->FormattedHardwareAddressForType(NetworkTypePattern::WiFi());
  }

  base::string16 bubble_text;
  auto add_line = [&bubble_text](const std::string& address, int ids) {
    if (!address.empty()) {
      if (!bubble_text.empty())
        bubble_text += base::ASCIIToUTF16("\n");

      bubble_text +=
          l10n_util::GetStringFUTF16(ids, base::UTF8ToUTF16(address));
    }
  };

  add_line(ip_address, IDS_ASH_STATUS_TRAY_IP_ADDRESS);
  add_line(ipv6_address, IDS_ASH_STATUS_TRAY_IPV6_ADDRESS);
  add_line(ethernet_address, IDS_ASH_STATUS_TRAY_ETHERNET_ADDRESS);
  add_line(wifi_address, IDS_ASH_STATUS_TRAY_WIFI_ADDRESS);

  // Avoid an empty bubble in the unlikely event that there is no network
  // information at all.
  if (bubble_text.empty())
    bubble_text = l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NO_NETWORKS);

  auto* label = new views::Label(bubble_text);
  label->SetMultiLine(true);
  label->SetHorizontalAlignment(gfx::ALIGN_TO_HEAD);
  label->SetSelectable(true);
  return label;
}

void NetworkStateListDetailedView::ScanAndStartTimer() {
  CallRequestScan();
  network_scan_repeating_timer_.Start(
      FROM_HERE, base::TimeDelta::FromSeconds(kRequestScanDelaySeconds), this,
      &NetworkStateListDetailedView::CallRequestScan);
}

void NetworkStateListDetailedView::CallRequestScan() {
  if (!IsWifiEnabled())
    return;

  VLOG(1) << "Requesting Network Scan.";
  NetworkHandler::Get()->network_state_handler()->RequestScan(
      NetworkTypePattern::WiFi() | NetworkTypePattern::Tether());
}

}  // namespace tray
}  // namespace ash
