import { toRefs, ref, watch, SetupContext } from 'vue';
import { MdPlugin, MdRenderProps } from '../editor-md-types';
import { MDRenderService } from './md-render-service';

export function useEditorMdRender(props: MdRenderProps, ctx: SetupContext) {
  const { content, customParse, disableRender } = toRefs(props);
  const renderService = new MDRenderService();
  const previewRef = ref();
  let timer: ReturnType<typeof setTimeout> | null = null;

  const setContainerContent = () => {
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      if (content.value === undefined) {
        return;
      }

      let html = renderService.generateHTML(content.value);
      if (customParse?.value && customParse.value instanceof Function) {
        html = customParse.value(html);
      }

      if (!disableRender.value && previewRef.value) {
        previewRef.value.innerHTML = html;
      }
      ctx.emit('mdRenderChange', html);
    }, 300);
  };

  const setChecked = (checked: boolean, index: number) => {
    const pattern = /\[(X|\s|\_|\-)\]\s(.*)/gi;
    let i = 0;
    const result = content.value.replace(pattern, (str) => {
      const arr = str.split('<br>');
      let j = 0;
      while (j < arr.length) {
        if (arr[j].match(/\[(X|\s|\_|\-)\]/i)) {
          i++;
        }
        if (i === index + 1) {
          arr[j] = arr[j].replace(/\[(X|\s|\_|\-)\]/i, `${checked ? '[x]' : '[ ]'}`);
        }
        j++;
      }
      return arr.join('<br>');
    });
    return result;
  };

  const onPreviewClick = (e: any) => {
    if (e.target?.tagName === 'INPUT' && e.target.type === 'checkbox') {
      const result = previewRef.value.querySelectorAll('input');
      const index = [...result].filter((el: any) => el.type === 'checkbox').findIndex((item: any) => item === e.target);
      const checkContent = setChecked(e.target.checked, index);
      ctx.emit('checkedChange', checkContent);
    }
  };

  return { previewRef, renderService, onPreviewClick, setContainerContent };
}

export function useMdRenderWatcher(props: MdRenderProps, renderService: MDRenderService, setContainerContent: () => void) {
  const { mdRules, content, customParse, renderParse, customXssRules, customRendererRules, baseUrl, breaks, mdPlugins } = toRefs(props);
  watch(
    mdRules,
    () => {
      renderService.setRules(mdRules?.value);
    },
    {
      immediate: true,
    }
  );

  watch(content, setContainerContent, { immediate: true });

  watch(customParse, setContainerContent, { immediate: true });

  watch(
    renderParse,
    () => {
      renderService.setRenderParse(renderParse?.value);
      setContainerContent();
    },
    { immediate: true }
  );

  watch(
    customXssRules,
    () => {
      renderService.setCustomXssRules(customXssRules.value);
      setContainerContent();
    },
    {
      immediate: true,
    }
  );

  watch(
    customRendererRules,
    () => {
      renderService.setCustomRendererRules(customRendererRules?.value);
      setContainerContent();
    },
    {
      immediate: true,
    }
  );

  watch(
    baseUrl,
    () => {
      renderService.setBaseUrl(baseUrl?.value);
      setContainerContent();
    },
    {
      immediate: true,
    }
  );

  watch(
    breaks,
    () => {
      renderService.setBreaks(breaks?.value);
      setContainerContent();
    },
    {
      immediate: true,
    }
  );

  watch(
    mdPlugins,
    (plugins: MdPlugin[]) => {
      if (plugins && plugins.length) {
        renderService.setPlugins(plugins);
        setContainerContent();
      }
    },
    {
      immediate: true,
    }
  );
}