/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

"use strict";

const {
  createFactory,
  PureComponent,
} = require("resource://devtools/client/shared/vendor/react.mjs");
const dom = require("resource://devtools/client/shared/vendor/react-dom-factories.js");
const { hr } = dom;
const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.mjs");

const {
  getStr,
} = require("resource://devtools/client/responsive/utils/l10n.js");
const {
  parseUserAgent,
} = require("resource://devtools/client/responsive/utils/ua.js");
const Types = require("resource://devtools/client/responsive/types.js");

const MenuButton = createFactory(
  require("resource://devtools/client/shared/components/menu/MenuButton.js")
);

loader.lazyGetter(this, "MenuItem", () => {
  const menuItemClass = require("resource://devtools/client/shared/components/menu/MenuItem.js");
  const menuItem = createFactory(menuItemClass);
  menuItem.DUMMY_ICON = menuItemClass.DUMMY_ICON;
  return menuItem;
});

loader.lazyGetter(this, "MenuList", () => {
  return createFactory(
    require("resource://devtools/client/shared/components/menu/MenuList.js")
  );
});

class DeviceSelector extends PureComponent {
  static get propTypes() {
    return {
      devices: PropTypes.shape(Types.devices).isRequired,
      onChangeDevice: PropTypes.func.isRequired,
      onUpdateDeviceModal: PropTypes.func.isRequired,
      selectedDevice: PropTypes.string.isRequired,
      viewportId: PropTypes.number.isRequired,
    };
  }

  getMenuProps(device) {
    if (!device) {
      return { icon: null, label: null, tooltip: null };
    }

    const { browser, os } = parseUserAgent(device.userAgent);
    let label = device.name;
    if (os) {
      label += ` ${os.name}`;
      if (os.version) {
        label += ` ${os.version}`;
      }
    }

    let icon = null;
    let tooltip = label;
    if (browser) {
      icon = `chrome://devtools/skin/images/browsers/${browser.name.toLowerCase()}.svg`;
      tooltip += ` ${browser.name} ${browser.version}`;
    }

    return { icon, label, tooltip };
  }

  getSelectedDevice() {
    const { devices, selectedDevice } = this.props;

    if (!selectedDevice) {
      return null;
    }

    for (const type of devices.types) {
      for (const device of devices[type]) {
        if (selectedDevice === device.name) {
          return device;
        }
      }
    }

    return null;
  }

  renderMenuList() {
    const {
      devices,
      onChangeDevice,
      onUpdateDeviceModal,
      selectedDevice,
      viewportId,
    } = this.props;

    const menuItems = [];

    for (const type of devices.types) {
      for (const device of devices[type]) {
        if (device.displayed) {
          const { icon, label, tooltip } = this.getMenuProps(device);

          menuItems.push(
            MenuItem({
              key: label,
              className: "device-selector-item",
              checked: selectedDevice === device.name,
              label,
              icon: icon || MenuItem.DUMMY_ICON,
              tooltip,
              onClick: () => onChangeDevice(viewportId, device, type),
            })
          );
        }
      }
    }

    menuItems.sort(function (a, b) {
      return a.props.label.localeCompare(b.props.label);
    });

    if (menuItems.length) {
      menuItems.push(hr({ key: "separator" }));
    }

    menuItems.push(
      MenuItem({
        key: "edit-device",
        label: getStr("responsive.editDeviceList2"),
        onClick: () => onUpdateDeviceModal(true, viewportId),
      })
    );

    return MenuList({}, menuItems);
  }

  render() {
    const { devices } = this.props;
    const selectedDevice = this.getSelectedDevice();
    let { icon, label, tooltip } = this.getMenuProps(selectedDevice);

    if (!selectedDevice) {
      label = getStr("responsive.responsiveMode");
    }

    // MenuButton is expected to be used in the toolbox document usually,
    // but since RDM's frame also loads theme-switching.js, we can create
    // MenuButtons (& HTMLTooltips) in the RDM frame document.
    const toolboxDoc = window.document;

    return MenuButton(
      {
        id: "device-selector",
        menuId: "device-selector-menu",
        toolboxDoc,
        className: "devtools-button devtools-dropdown-button",
        label,
        icon,
        title: tooltip,
        disabled: devices.listState !== Types.loadableState.LOADED,
      },
      () => this.renderMenuList()
    );
  }
}

module.exports = DeviceSelector;
