import { startsWith, get } from "lodash";
import React from "react";
import PropTypes from "prop-types";
import cx from "classnames";
import Tooltip from "antd/lib/tooltip";
import Drawer from "antd/lib/drawer";
import Icon from "antd/lib/icon";
import BigMessage from "@/components/BigMessage";
import DynamicComponent from "@/components/DynamicComponent";

import "./HelpTrigger.less";

const DOMAIN = "https://redash.io";
const HELP_PATH = "/help";
const IFRAME_TIMEOUT = 20000;
const IFRAME_URL_UPDATE_MESSAGE = "iframe_url";

export const TYPES = {
  HOME: ["", "Help"],
  VALUE_SOURCE_OPTIONS: ["/user-guide/querying/query-parameters#Value-Source-Options", "Guide: Value Source Options"],
  SHARE_DASHBOARD: ["/user-guide/dashboards/sharing-dashboards", "Guide: Sharing and Embedding Dashboards"],
  AUTHENTICATION_OPTIONS: ["/user-guide/users/authentication-options", "Guide: Authentication Options"],
  USAGE_DATA_SHARING: ["/open-source/admin-guide/usage-data", "Help: Anonymous Usage Data Sharing"],
  DS_ATHENA: ["/data-sources/amazon-athena-setup", "Guide: Help Setting up Amazon Athena"],
  DS_BIGQUERY: ["/data-sources/bigquery-setup", "Guide: Help Setting up BigQuery"],
  DS_URL: ["/data-sources/querying-urls", "Guide: Help Setting up URL"],
  DS_MONGODB: ["/data-sources/mongodb-setup", "Guide: Help Setting up MongoDB"],
  DS_GOOGLE_SPREADSHEETS: ["/data-sources/querying-a-google-spreadsheet", "Guide: Help Setting up Google Spreadsheets"],
  DS_GOOGLE_ANALYTICS: ["/data-sources/google-analytics-setup", "Guide: Help Setting up Google Analytics"],
  DS_AXIBASETSD: ["/data-sources/axibase-time-series-database", "Guide: Help Setting up Axibase Time Series"],
  DS_RESULTS: ["/user-guide/querying/query-results-data-source", "Guide: Help Setting up Query Results"],
  ALERT_SETUP: ["/user-guide/alerts/setting-up-an-alert", "Guide: Setting Up a New Alert"],
  MAIL_CONFIG: ["/open-source/setup/#Mail-Configuration", "Guide: Mail Configuration"],
  ALERT_NOTIF_TEMPLATE_GUIDE: ["/user-guide/alerts/custom-alert-notifications", "Guide: Custom Alerts Notifications"],
  FAVORITES: ["/user-guide/querying/favorites-tagging/#Favorites", "Guide: Favorites"],
  MANAGE_PERMISSIONS: [
    "/user-guide/querying/writing-queries#Managing-Query-Permissions",
    "Guide: Managing Query Permissions",
  ],
  NUMBER_FORMAT_SPECS: ["/user-guide/visualizations/formatting-numbers", "Formatting Numbers"],
};

export default class HelpTrigger extends React.Component {
  static propTypes = {
    type: PropTypes.oneOf(Object.keys(TYPES)),
    href: PropTypes.string,
    title: PropTypes.node,
    className: PropTypes.string,
    showTooltip: PropTypes.bool,
    children: PropTypes.node,
  };

  static defaultProps = {
    type: null,
    href: null,
    title: null,
    className: null,
    showTooltip: true,
    children: <i className="fa fa-question-circle" />,
  };

  iframeRef = React.createRef();

  iframeLoadingTimeout = null;

  state = {
    visible: false,
    loading: false,
    error: false,
    currentUrl: null,
  };

  componentDidMount() {
    window.addEventListener("message", this.onPostMessageReceived, false);
  }

  componentWillUnmount() {
    window.removeEventListener("message", this.onPostMessageReceived);
    clearTimeout(this.iframeLoadingTimeout);
  }

  loadIframe = url => {
    clearTimeout(this.iframeLoadingTimeout);
    this.setState({ loading: true, error: false });

    this.iframeRef.current.src = url;
    this.iframeLoadingTimeout = setTimeout(() => {
      this.setState({ error: url, loading: false });
    }, IFRAME_TIMEOUT); // safety
  };

  onIframeLoaded = () => {
    this.setState({ loading: false });
    clearTimeout(this.iframeLoadingTimeout);
  };

  onPostMessageReceived = event => {
    if (!startsWith(event.origin, DOMAIN)) {
      return;
    }

    const { type, message: currentUrl } = event.data || {};
    if (type !== IFRAME_URL_UPDATE_MESSAGE) {
      return;
    }

    this.setState({ currentUrl });
  };

  getUrl = () => {
    const helpTriggerType = get(TYPES, this.props.type);
    return helpTriggerType ? DOMAIN + HELP_PATH + helpTriggerType[0] : this.props.href;
  };

  openDrawer = () => {
    this.setState({ visible: true });
    // wait for drawer animation to complete so there's no animation jank
    setTimeout(() => this.loadIframe(this.getUrl()), 300);
  };

  closeDrawer = event => {
    if (event) {
      event.preventDefault();
    }
    this.setState({ visible: false });
    this.setState({ visible: false, currentUrl: null });
  };

  render() {
    const tooltip = get(TYPES, `${this.props.type}[1]`, this.props.title);
    const className = cx("help-trigger", this.props.className);
    const url = this.state.currentUrl;

    const isAllowedDomain = startsWith(url || this.getUrl(), DOMAIN);

    return (
      <React.Fragment>
        <Tooltip
          title={
            this.props.showTooltip ? (
              <>
                {tooltip}
                {!isAllowedDomain && <i className="fa fa-external-link" style={{ marginLeft: 5 }} />}
              </>
            ) : null
          }>
          {isAllowedDomain ? (
            <a onClick={this.openDrawer} className={className}>
              {this.props.children}
            </a>
          ) : (
            <a href={url || this.getUrl()} className={className} rel="noopener noreferrer" target="_blank">
              {this.props.children}
            </a>
          )}
        </Tooltip>
        <Drawer
          placement="right"
          closable={false}
          onClose={this.closeDrawer}
          visible={this.state.visible}
          className="help-drawer"
          destroyOnClose
          width={400}>
          <div className="drawer-wrapper">
            <div className="drawer-menu">
              {url && (
                <Tooltip title="Open page in a new window" placement="left">
                  {/* eslint-disable-next-line react/jsx-no-target-blank */}
                  <a href={url} target="_blank">
                    <i className="fa fa-external-link" />
                  </a>
                </Tooltip>
              )}
              <Tooltip title="Close" placement="bottom">
                <a onClick={this.closeDrawer}>
                  <Icon type="close" />
                </a>
              </Tooltip>
            </div>

            {/* iframe */}
            {!this.state.error && (
              <iframe
                ref={this.iframeRef}
                title="Redash Help"
                src="about:blank"
                className={cx({ ready: !this.state.loading })}
                onLoad={this.onIframeLoaded}
              />
            )}

            {/* loading indicator */}
            {this.state.loading && (
              <BigMessage icon="fa-spinner fa-2x fa-pulse" message="Loading..." className="help-message" />
            )}

            {/* error message */}
            {this.state.error && (
              <BigMessage icon="fa-exclamation-circle" className="help-message">
                Something went wrong.
                <br />
                {/* eslint-disable-next-line react/jsx-no-target-blank */}
                <a href={this.state.error} target="_blank" rel="noopener">
                  Click here
                </a>{" "}
                to open the page in a new window.
              </BigMessage>
            )}
          </div>

          {/* extra content */}
          <DynamicComponent name="HelpDrawerExtraContent" onLeave={this.closeDrawer} openPageUrl={this.loadIframe} />
        </Drawer>
      </React.Fragment>
    );
  }
}
