import { CreateElement, VNodeData } from 'vue';
import { VNodeChildren } from 'vue/types/vnode';
import {
  AsyncComponentFactory,
  AsyncComponentPromise,
  Component,
  FunctionalComponentOptions,
} from 'vue/types/options';

export function lazyLoadView(
  AsyncView: Promise<unknown>
): Promise<FunctionalComponentOptions> {
  const AsyncHandler: AsyncComponentFactory = () => ({
    // todo fix param typing - dynamic import
    component: (AsyncView as unknown) as AsyncComponentPromise,
    // A component to use while the component is loading.
    // eslint-disable-next-line @typescript-eslint/no-var-requires
    loading: require('../router/common/_loading.vue').default,
    // Delay before showing the loading component.
    // Default: 200 (milliseconds).
    delay: 400,
    // A fallback component in case the timeout is exceeded
    // when loading the component.
    // eslint-disable-next-line @typescript-eslint/no-var-requires
    error: require('../router/common/_timeout.vue').default,
    // Time before giving up trying to load the component.
    // Default: Infinity (milliseconds).
    timeout: 10000,
  });

  return Promise.resolve({
    functional: true,
    render(
      h: CreateElement,
      {
        data,
        children,
      }: {
        data: VNodeData;
        children: VNodeChildren;
      }
    ) {
      // Transparently pass any props or children
      // to the view component.
      return h(AsyncHandler as () => Component, data, children);
    },
  });
}
