import React, {
 lazy, Suspense, useMemo, useState, useEffect,
} from 'react';
import cloneDeep from 'lodash/cloneDeep';
import Skeleton from '@material-ui/lab/Skeleton';
import Loading from '@Components/Base/Loading';
import { Props, ComponentState } from './types';

const Components: { [key: string]: ComponentState } = {};

const Lazy: React.FC<Props> = (props): React.ReactElement => {
  const { componentImport, componentChunkName, componentProps } = props;
  const [isRender, setIsRender] = useState(false);
  const RenderComponent = useMemo(() => {
    const Component = Components[componentChunkName];
    if (Component) {
      return <Component {...componentProps} />;
    }
    return (
      <div style={{ width: '100%', height: '100%' }}>
        <Loading typePosition="relative" typeZIndex={10005} typeIcon="line:fix" isLoading />
        <Skeleton variant="rect" width="100%" height="100%" animation="wave" />
      </div>
    );
  }, [componentChunkName, isRender, componentProps]);
  /* Hooks */
  useEffect(() => {
    (async () => {
      if (!Components[componentChunkName]) {
        Components[componentChunkName] = lazy(async () => {
          const Element = await componentImport;
          return Element;
        });
      }
      setIsRender(cloneDeep(!isRender));
    })();
  }, [componentChunkName]);
  return (
    <React.Fragment>
      <Suspense fallback={<Loading typePosition="relative" typeZIndex={10005} typeIcon="line:fix" isLoading />}>
        {RenderComponent}
      </Suspense>
    </React.Fragment>
  );
};

export default Lazy;
