import React, { useRef, useEffect, isValidElement, useMemo } from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import introJS, { IntroJs } from 'intro.js';
import { IntroProps } from './xui-intro.d';

const XuiIntro: React.FC<IntroProps> = ({
  enabled,
  initialStep,
  options,
  steps,
  onChange = () => {},
  onComplete = () => {},
  onExit = () => {},
}) => {
  const introJs = useRef<any>(null);
  const isConfigured = useRef(false);
  const isVisible = useRef(false);

  const defalutOptions = useMemo(
    () => ({
      prevLabel: '上一步',
      nextLabel: '下一步',
      skipLabel: '跳过',
      doneLabel: '完成',
      showStepNumbers: false,
      overlayOpacity: 0.45,
      showBullets: false,
      highlightClass: 'xui-ant__intro--highlightClass',
      tooltipClass: 'xui-ant__intro--tooltipClass',
      exitOnOverlayClick: false,
    }),
    [],
  );

  const configureIntroJs = () => {
    const sanitizedSteps = steps.map(step => {
      if (isValidElement(step.intro)) {
        return {
          ...step,
          intro: renderToStaticMarkup(step.intro),
        };
      }

      return step;
    });

    const introJsCurrent: IntroJs = introJs.current;
    introJsCurrent.setOptions({ ...defalutOptions, ...options, steps: sanitizedSteps });
    isConfigured.current = true;
  };

  const renderSteps = () => {
    if (enabled && steps.length > 0 && !isVisible.current) {
      const introJsCurrent: IntroJs = introJs.current;
      introJsCurrent.start();

      isVisible.current = true;

      introJsCurrent.goToStepNumber(initialStep + 1);
    } else if (!enabled && isVisible.current) {
      isVisible.current = false;

      introJs.current.exit();
    }
  };

  const handleExit = () => {
    isVisible.current = false;

    onExit();
  };

  const handleChange = (element: any) => {
    if (!isVisible.current) {
      return;
    }

    if (onChange) {
      onChange(element);
    }
  };

  const handleComplete = () => {
    if (onComplete) {
      onComplete();
    }
  };

  useEffect(() => {
    introJs.current = introJS();
    const introJsCurrent: IntroJs = introJs.current;
    introJsCurrent.onexit(handleExit);
    introJsCurrent.onchange(handleChange);
    introJsCurrent.oncomplete(handleComplete);
    return () => {
      introJsCurrent.exit();
    };
  }, []);

  useEffect(() => {
    if (enabled) {
      configureIntroJs();
      renderSteps();
    }
  }, [enabled, steps, options]);

  return null;
};

export default XuiIntro;
