/* 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 PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.mjs");
const {
  withRouter,
} = require("resource://devtools/client/shared/vendor/react-router-dom.js");

const FluentReact = require("resource://devtools/client/shared/vendor/fluent-react.js");
const Localized = createFactory(FluentReact.Localized);

const Message = createFactory(
  require("resource://devtools/client/aboutdebugging/src/components/shared/Message.js")
);
const SidebarItem = createFactory(
  require("resource://devtools/client/aboutdebugging/src/components/sidebar/SidebarItem.js")
);
const Actions = require("resource://devtools/client/aboutdebugging/src/actions/index.js");
const {
  MESSAGE_LEVEL,
} = require("resource://devtools/client/aboutdebugging/src/constants.js");

/**
 * This component displays a runtime item of the Sidebar component.
 */
class SidebarRuntimeItem extends PureComponent {
  static get propTypes() {
    return {
      deviceName: PropTypes.string,
      dispatch: PropTypes.func.isRequired,
      // Provided by wrapping the component with FluentReact.withLocalization.
      getString: PropTypes.func.isRequired,
      icon: PropTypes.string.isRequired,
      isConnected: PropTypes.bool.isRequired,
      isConnecting: PropTypes.bool.isRequired,
      isConnectionFailed: PropTypes.bool.isRequired,
      isConnectionNotResponding: PropTypes.bool.isRequired,
      isConnectionTimeout: PropTypes.bool.isRequired,
      isSelected: PropTypes.bool.isRequired,
      isUnavailable: PropTypes.bool.isRequired,
      isUnplugged: PropTypes.bool.isRequired,
      name: PropTypes.string.isRequired,
      runtimeId: PropTypes.string.isRequired,

      // Provided by react-router
      match: PropTypes.object.isRequired,
      location: PropTypes.object.isRequired,
      history: PropTypes.object.isRequired,
    };
  }

  renderConnectButton() {
    const { isConnecting, history } = this.props;
    const localizationId = isConnecting
      ? "about-debugging-sidebar-item-connect-button-connecting"
      : "about-debugging-sidebar-item-connect-button";
    return Localized(
      {
        id: localizationId,
      },
      dom.button(
        {
          className: "default-button default-button--micro qa-connect-button",
          disabled: isConnecting,
          onClick: async () => {
            const { dispatch, runtimeId } = this.props;
            await dispatch(Actions.connectRuntime(runtimeId));
            if (this.props.isConnected) {
              // If the connection was successful, navigate to the new runtime.
              // Note: By using `this.props`, the latest value is retrieved, as
              // the result of the `connectRuntime` action. If we had used a
              // destructuring assignment at the start of the
              // `renderConnectButton` function instead, we'd have captured the
              // initial (outdated) value instead.
              history.push("/runtime/" + encodeURIComponent(runtimeId));
            }
          },
        },
        localizationId
      )
    );
  }

  renderMessage(flag, level, localizationId, className) {
    if (!flag) {
      return null;
    }

    return Message(
      {
        level,
        className: `${className} sidebar-runtime-item__message`,
        isCloseable: true,
      },
      Localized(
        {
          id: localizationId,
        },
        dom.p({ className: "word-wrap-anywhere" }, localizationId)
      )
    );
  }

  renderName() {
    const { deviceName, getString, isUnavailable, isUnplugged, name } =
      this.props;

    let displayName, qaClassName;
    if (isUnplugged) {
      displayName = getString("about-debugging-sidebar-runtime-item-unplugged");
      qaClassName = "qa-runtime-item-unplugged";
    } else if (isUnavailable) {
      displayName = getString(
        "about-debugging-sidebar-runtime-item-waiting-for-browser"
      );
      qaClassName = "qa-runtime-item-waiting-for-browser";
    } else {
      displayName = name;
      qaClassName = "qa-runtime-item-standard";
    }

    const localizationId = deviceName
      ? "about-debugging-sidebar-runtime-item-name"
      : "about-debugging-sidebar-runtime-item-name-no-device";

    const className = "ellipsis-text sidebar-runtime-item__runtime";

    function renderWithDevice() {
      return dom.span(
        {
          className,
          title: localizationId,
        },
        deviceName,
        dom.br({}),
        dom.span(
          {
            className: `sidebar-runtime-item__runtime__details ${qaClassName}`,
          },
          displayName
        )
      );
    }

    function renderNoDevice() {
      return dom.span(
        {
          className,
          title: localizationId,
        },
        displayName
      );
    }

    return Localized(
      {
        id: localizationId,
        attrs: { title: true },
        $deviceName: deviceName,
        $displayName: displayName,
      },
      deviceName ? renderWithDevice() : renderNoDevice()
    );
  }

  render() {
    const {
      getString,
      icon,
      isConnected,
      isConnectionFailed,
      isConnectionTimeout,
      isConnectionNotResponding,
      isSelected,
      isUnavailable,
      runtimeId,
    } = this.props;

    const connectionStatus = isConnected
      ? getString("aboutdebugging-sidebar-runtime-connection-status-connected")
      : getString(
          "aboutdebugging-sidebar-runtime-connection-status-disconnected"
        );

    return SidebarItem(
      {
        isSelected,
        to: isConnected ? `/runtime/${encodeURIComponent(runtimeId)}` : null,
      },
      dom.section(
        {
          className: "sidebar-runtime-item__container",
        },
        dom.img({
          className: "sidebar-runtime-item__icon ",
          src: icon,
          alt: connectionStatus,
          title: connectionStatus,
        }),
        this.renderName(),
        !isUnavailable && !isConnected ? this.renderConnectButton() : null
      ),
      this.renderMessage(
        isConnectionFailed,
        MESSAGE_LEVEL.ERROR,
        "about-debugging-sidebar-item-connect-button-connection-failed",
        "qa-connection-error"
      ),
      this.renderMessage(
        isConnectionTimeout,
        MESSAGE_LEVEL.ERROR,
        "about-debugging-sidebar-item-connect-button-connection-timeout",
        "qa-connection-timeout"
      ),
      this.renderMessage(
        isConnectionNotResponding,
        MESSAGE_LEVEL.WARNING,
        "about-debugging-sidebar-item-connect-button-connection-not-responding",
        "qa-connection-not-responding"
      )
    );
  }
}

module.exports = withRouter(FluentReact.withLocalization(SidebarRuntimeItem));
