// 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/ui/webui/chromeos/imageburner/imageburner_ui.h"

#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/i18n/rtl.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/chromeos/imageburner/burn_controller.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/browser/web_ui_message_handler.h"
#include "grit/browser_resources.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/l10n/time_format.h"
#include "ui/base/text/bytes_formatting.h"
#include "url/gurl.h"

namespace chromeos {
namespace imageburner {

namespace {

const char kPropertyDevicePath[] = "devicePath";
const char kPropertyFilePath[] = "filePath";
const char kPropertyLabel[] = "label";
const char kPropertyPath[] = "path";
const char kPropertyDeviceType[] = "type";

// Link displayed on imageburner ui.
const char kMoreInfoLink[] =
    "http://www.chromium.org/chromium-os/chromiumos-design-docs/recovery-mode";

content::WebUIDataSource* CreateImageburnerUIHTMLSource() {
  content::WebUIDataSource* source =
      content::WebUIDataSource::Create(chrome::kChromeUIImageBurnerHost);

  source->AddLocalizedString("headerTitle", IDS_IMAGEBURN_HEADER_TITLE);
  source->AddLocalizedString("headerDescription",
                             IDS_IMAGEBURN_HEADER_DESCRIPTION);
  source->AddLocalizedString("headerLink", IDS_IMAGEBURN_HEADER_LINK);
  source->AddLocalizedString("statusDevicesNone",
                             IDS_IMAGEBURN_NO_DEVICES_STATUS);
  source->AddLocalizedString("warningDevicesNone",
                             IDS_IMAGEBURN_NO_DEVICES_WARNING);
  source->AddLocalizedString("statusDevicesMultiple",
                             IDS_IMAGEBURN_MUL_DEVICES_STATUS);
  source->AddLocalizedString("statusDeviceUSB",
                             IDS_IMAGEBURN_USB_DEVICE_STATUS);
  source->AddLocalizedString("statusDeviceSD",
                             IDS_IMAGEBURN_SD_DEVICE_STATUS);
  source->AddLocalizedString("warningDevices",
                             IDS_IMAGEBURN_DEVICES_WARNING);
  source->AddLocalizedString("statusNoConnection",
                             IDS_IMAGEBURN_NO_CONNECTION_STATUS);
  source->AddLocalizedString("warningNoConnection",
                             IDS_IMAGEBURN_NO_CONNECTION_WARNING);
  source->AddLocalizedString("statusNoSpace",
                             IDS_IMAGEBURN_INSUFFICIENT_SPACE_STATUS);
  source->AddLocalizedString("warningNoSpace",
                             IDS_IMAGEBURN_INSUFFICIENT_SPACE_WARNING);
  source->AddLocalizedString("statusDownloading",
                             IDS_IMAGEBURN_DOWNLOADING_STATUS);
  source->AddLocalizedString("statusUnzip", IDS_IMAGEBURN_UNZIP_STATUS);
  source->AddLocalizedString("statusBurn", IDS_IMAGEBURN_BURN_STATUS);
  source->AddLocalizedString("statusError", IDS_IMAGEBURN_ERROR_STATUS);
  source->AddLocalizedString("statusSuccess", IDS_IMAGEBURN_SUCCESS_STATUS);
  source->AddLocalizedString("warningSuccess", IDS_IMAGEBURN_SUCCESS_DESC);
  source->AddLocalizedString("title", IDS_IMAGEBURN_PAGE_TITLE);
  source->AddLocalizedString("confirmButton", IDS_IMAGEBURN_CONFIRM_BUTTON);
  source->AddLocalizedString("cancelButton", IDS_IMAGEBURN_CANCEL_BUTTON);
  source->AddLocalizedString("retryButton", IDS_IMAGEBURN_RETRY_BUTTON);
  source->AddString("moreInfoLink", ASCIIToUTF16(kMoreInfoLink));

  source->SetJsonPath("strings.js");
  source->AddResourcePath("image_burner.js", IDR_IMAGEBURNER_JS);
  source->SetDefaultResource(IDR_IMAGEBURNER_HTML);
  return source;
}

class WebUIHandler
    : public content::WebUIMessageHandler,
      public BurnController::Delegate {
 public:
  explicit WebUIHandler(content::WebContents* contents)
      : burn_controller_(BurnController::CreateBurnController(contents, this)){
  }

  virtual ~WebUIHandler() {
  }

  // WebUIMessageHandler implementation.
  virtual void RegisterMessages() OVERRIDE {
    web_ui()->RegisterMessageCallback(
        "getDevices",
        base::Bind(&WebUIHandler::HandleGetDevices, base::Unretained(this)));
    web_ui()->RegisterMessageCallback(
        "burnImage",
        base::Bind(&WebUIHandler::HandleBurnImage, base::Unretained(this)));
    web_ui()->RegisterMessageCallback(
        "cancelBurnImage",
        base::Bind(&WebUIHandler::HandleCancelBurnImage,
                   base::Unretained(this)));
    web_ui()->RegisterMessageCallback(
        "webuiInitialized",
        base::Bind(&WebUIHandler::HandleWebUIInitialized,
                   base::Unretained(this)));
  }

  // BurnController::Delegate override.
  virtual void OnSuccess() OVERRIDE {
    web_ui()->CallJavascriptFunction("browserBridge.reportSuccess");
  }

  // BurnController::Delegate override.
  virtual void OnFail(int error_message_id) OVERRIDE {
    StringValue error_message(l10n_util::GetStringUTF16(error_message_id));
    web_ui()->CallJavascriptFunction("browserBridge.reportFail", error_message);
  }

  // BurnController::Delegate override.
  virtual void OnDeviceAdded(const disks::DiskMountManager::Disk& disk)
      OVERRIDE {
    DictionaryValue disk_value;
    CreateDiskValue(disk, &disk_value);
    web_ui()->CallJavascriptFunction("browserBridge.deviceAdded", disk_value);
  }

  // BurnController::Delegate override.
  virtual void OnDeviceRemoved(const disks::DiskMountManager::Disk& disk)
      OVERRIDE {
    StringValue device_path_value(disk.device_path());
    web_ui()->CallJavascriptFunction("browserBridge.deviceRemoved",
                                     device_path_value);
  }

  // BurnController::Delegate override.
  virtual void OnDeviceTooSmall(int64 device_size) OVERRIDE {
    string16 size;
    GetDataSizeText(device_size, &size);
    StringValue device_size_text(size);
    web_ui()->CallJavascriptFunction("browserBridge.reportDeviceTooSmall",
                                     device_size_text);
  }

  // BurnController::Delegate override.
  virtual void OnProgress(ProgressType progress_type,
                          int64 amount_finished,
                          int64 amount_total) OVERRIDE {
    const string16 time_remaining_text =
        l10n_util::GetStringUTF16(IDS_IMAGEBURN_PROGRESS_TIME_UNKNOWN);
    SendProgressSignal(progress_type, amount_finished, amount_total,
                       time_remaining_text);
  }

  // BurnController::Delegate override.
  virtual void OnProgressWithRemainingTime(
      ProgressType progress_type,
      int64 amount_finished,
      int64 amount_total,
      const base::TimeDelta& time_remaining) OVERRIDE {
    const string16 time_remaining_text = l10n_util::GetStringFUTF16(
        IDS_IMAGEBURN_DOWNLOAD_TIME_REMAINING,
        ui::TimeFormat::TimeRemaining(time_remaining));
    SendProgressSignal(progress_type, amount_finished, amount_total,
                       time_remaining_text);
  }

  // BurnController::Delegate override.
  virtual void OnNetworkDetected() OVERRIDE {
    web_ui()->CallJavascriptFunction("browserBridge.reportNetworkDetected");
  }

  // BurnController::Delegate override.
  virtual void OnNoNetwork() OVERRIDE {
    web_ui()->CallJavascriptFunction("browserBridge.reportNoNetwork");
  }

 private:
  void CreateDiskValue(const disks::DiskMountManager::Disk& disk,
                       DictionaryValue* disk_value) {
    string16 label = ASCIIToUTF16(disk.drive_label());
    base::i18n::AdjustStringForLocaleDirection(&label);
    disk_value->SetString(std::string(kPropertyLabel), label);
    disk_value->SetString(std::string(kPropertyFilePath), disk.file_path());
    disk_value->SetString(std::string(kPropertyDevicePath), disk.device_path());
    disk_value->SetString(std::string(kPropertyDeviceType),
        disks::DiskMountManager::DeviceTypeToString(disk.device_type()));
  }

  // Callback for the "getDevices" message.
  void HandleGetDevices(const ListValue* args) {
    const std::vector<disks::DiskMountManager::Disk> disks
        = burn_controller_->GetBurnableDevices();
    ListValue results_value;
    for (size_t i = 0; i != disks.size(); ++i) {
      DictionaryValue* disk_value = new DictionaryValue();
      CreateDiskValue(disks[i], disk_value);
      results_value.Append(disk_value);
    }
    web_ui()->CallJavascriptFunction("browserBridge.getDevicesCallback",
                                     results_value);
  }

  // Callback for the webuiInitialized message.
  void HandleWebUIInitialized(const ListValue* args) {
    burn_controller_->Init();
  }

  // Callback for the "cancelBurnImage" message.
  void HandleCancelBurnImage(const ListValue* args) {
    burn_controller_->CancelBurnImage();
  }

  // Callback for the "burnImage" message.
  // It may be called with NULL if there is a handler that has started burning,
  // and thus set the target paths.
  void HandleBurnImage(const ListValue* args) {
    base::FilePath target_device_path;
    ExtractTargetedDevicePath(*args, 0, &target_device_path);

    base::FilePath target_file_path;
    ExtractTargetedDevicePath(*args, 1, &target_file_path);

    burn_controller_->StartBurnImage(target_device_path, target_file_path);
  }

  // Reports update to UI
  void SendProgressSignal(ProgressType progress_type,
                          int64 amount_finished,
                          int64 amount_total,
                          const string16& time_remaining_text) {
    DictionaryValue progress;
    int progress_message_id = 0;
    switch (progress_type) {
      case DOWNLOADING:
        progress.SetString("progressType", "download");
        progress_message_id = IDS_IMAGEBURN_DOWNLOAD_PROGRESS_TEXT;
        break;
      case UNZIPPING:
        progress.SetString("progressType", "unzip");
        break;
      case BURNING:
        progress.SetString("progressType", "burn");
        progress_message_id = IDS_IMAGEBURN_BURN_PROGRESS_TEXT;
        break;
      default:
        return;
    }

    progress.SetInteger("amountFinished", amount_finished);
    progress.SetInteger("amountTotal", amount_total);
    if (amount_total != 0) {
      string16 progress_text;
      GetProgressText(progress_message_id, amount_finished, amount_total,
                      &progress_text);
      progress.SetString("progressText", progress_text);
    } else {
      progress.SetString("progressText", "");
    }
    progress.SetString("timeLeftText", time_remaining_text);

    web_ui()->CallJavascriptFunction("browserBridge.updateProgress", progress);
  }

  // size_text should be previously created.
  void GetDataSizeText(int64 size, string16* size_text) {
    *size_text = ui::FormatBytes(size);
    base::i18n::AdjustStringForLocaleDirection(size_text);
  }

  // progress_text should be previously created.
  void GetProgressText(int message_id,
                       int64 amount_finished,
                       int64 amount_total,
                       string16* progress_text) {
    string16 finished;
    GetDataSizeText(amount_finished, &finished);
    string16 total;
    GetDataSizeText(amount_total, &total);
    *progress_text = l10n_util::GetStringFUTF16(message_id, finished, total);
  }

  // device_path has to be previously created.
  void ExtractTargetedDevicePath(const ListValue& list_value,
                                 int index,
                                 base::FilePath* device_path) {
    const Value* list_member;
    std::string image_dest;
    if (list_value.Get(index, &list_member) &&
        list_member->GetType() == Value::TYPE_STRING &&
        list_member->GetAsString(&image_dest)) {
      *device_path = base::FilePath(image_dest);
    } else {
      LOG(ERROR) << "Unable to get path string";
      device_path->clear();
    }
  }

  scoped_ptr<BurnController> burn_controller_;

  DISALLOW_COPY_AND_ASSIGN(WebUIHandler);
};

}  // namespace

}  // namespace imageburner
}  // namespace chromeos

////////////////////////////////////////////////////////////////////////////////
//
// ImageBurnUI
//
////////////////////////////////////////////////////////////////////////////////

ImageBurnUI::ImageBurnUI(content::WebUI* web_ui) : WebUIController(web_ui) {
  chromeos::imageburner::WebUIHandler* handler =
      new chromeos::imageburner::WebUIHandler(web_ui->GetWebContents());
  web_ui->AddMessageHandler(handler);

  Profile* profile = Profile::FromWebUI(web_ui);
  content::WebUIDataSource::Add(
      profile, chromeos::imageburner::CreateImageburnerUIHTMLSource());
}
