/**
 * TEAM: frontend_infra
 *
 * @flow
 */

import * as React from "react";
import {storiesOf} from "@storybook/react";
import {number, withKnobs, boolean, select} from "@storybook/addon-knobs";
import sections from "../sections";
import DeprecatedConnectedToaster from "../../toast/DeprecatedConnectedToaster";
import GeneralModalLoader from "../../modal/GeneralModalLoader";
import Button from "../../button/Button";
import typeof GeneralModalLoaderStoryExampleModalType from "./GeneralModalLoaderStoryExampleModal";

// $FlowFixMe[invalid-export]
const stories = storiesOf(sections.modals, module);
stories.addDecorator(withKnobs);

stories.add("GeneralModalLoader", () => (
  <GeneralModalLoaderHoist {...getLoaderModalKnobs()} />
));

type DynamicCompPromise<C> = Promise<{default: C, ...}>;
let slowPromiseTimerID: TimeoutID;
/**
 * Testing only: slowPromise is responsible for the time delay for right when the form data chunk loads from promise
 */
function slowPromiseFn<C>(
  targetPromiseFn: () => DynamicCompPromise<C>,
  delayTimeInMs: number
): () => DynamicCompPromise<C> {
  return () =>
    new Promise((resolve, reject) => {
      slowPromiseTimerID = setTimeout(() => {
        targetPromiseFn()
          .then(result => {
            resolve(result);
          })
          .catch(error => reject(error));
      }, delayTimeInMs);
    });
}

const getLoaderModalKnobs = () => ({
  dataLoadDelayInMs: number("dataLoadDelayInMs", 2000),
  preModalDelayMillis: number("preModalDelayMillis", 100),
  afterModalIsOpenMinLoaderDisplayMillis: number(
    "afterModalIsOpenMinLoaderDisplayMillis",
    2000
  ),
  timeoutMillis: number("timeoutMillis", 10000),
  onCloseAfterErrorDelayMillis: number("onCloseAfterErrorDelayMillis", 5000),
  shouldThrowError: boolean("shouldThrowError", false),
  width: select("width", ["s", "m", "l"], "m"),
});

type Props = {|
  +afterModalIsOpenMinLoaderDisplayMillis: number,
  +dataLoadDelayInMs: number,
  +onCloseAfterErrorDelayMillis: number,
  +preModalDelayMillis: number,
  +shouldThrowError: boolean,
  +timeoutMillis: number,
  +width: "s" | "m" | "l",
|};

class GeneralModalLoaderHoist extends React.PureComponent<
  Props,
  {isOpen: boolean, ...}
> {
  constructor(props: Props) {
    super(props);
    this.state = {isOpen: false};
  }

  handleCloseModal = () => {
    this.setState({isOpen: false});
  };

  handleOpen = () => {
    this.setState({isOpen: true});
  };

  componentWillUnmount() {
    clearTimeout(slowPromiseTimerID);
  }

  render() {
    return (
      <>
        <DeprecatedConnectedToaster />
        <Button onClick={this.handleOpen}>Open Modal</Button>
        {this.state.isOpen ? (
          <GeneralModalLoader
            component={
              this.props.shouldThrowError
                ? () =>
                    Promise.reject(
                      new Error("Test error triggered from storybook")
                    )
                : (slowPromiseFn(
                    () =>
                      import(
                        /* webpackChunkName: "latitude_stories_modals_GeneralModalLoaderStoryExampleModal" */ "./GeneralModalLoaderStoryExampleModal"
                      ),
                    this.props && this.props.dataLoadDelayInMs
                      ? this.props.dataLoadDelayInMs
                      : 5000
                  ): () => Promise<{
                    default: GeneralModalLoaderStoryExampleModalType,
                    ...
                  }>)
            }
            onClose={this.handleCloseModal}
            title="Create New User"
            width={this.props.width}
            _debug={{
              preModalDelayMillis:
                this.props && this.props.preModalDelayMillis
                  ? this.props.preModalDelayMillis
                  : 0,
              afterModalIsOpenMinLoaderDisplayMillis:
                this.props && this.props.afterModalIsOpenMinLoaderDisplayMillis
                  ? this.props.afterModalIsOpenMinLoaderDisplayMillis
                  : 2000,
              onCloseAfterErrorDelayMillis:
                this.props && this.props.onCloseAfterErrorDelayMillis
                  ? this.props.onCloseAfterErrorDelayMillis
                  : 0,
              timeoutMillis:
                this.props && this.props.timeoutMillis
                  ? this.props.timeoutMillis
                  : 10000,
            }}
          >
            {(ExampleModal: GeneralModalLoaderStoryExampleModalType) => (
              <ExampleModal onClose={this.handleCloseModal} />
            )}
          </GeneralModalLoader>
        ) : null}
      </>
    );
  }
}
