import { computed, createComponent, ref, watch, onBeforeUnmount, h, Transition, hSlot, QSpinner } from './__federation_expose_Modules-a9c6a6fc.js';

const useRatioProps = {
  ratio: [ String, Number ]
};

function useRatio (props, naturalRatio) {
  // return ratioStyle
  return computed(() => {
    const ratio = Number(
      props.ratio || (naturalRatio !== void 0 ? naturalRatio.value : void 0)
    );

    return isNaN(ratio) !== true && ratio > 0
      ? { paddingBottom: `${ 100 / ratio }%` }
      : null
  })
}

const defaultRatio = 16 / 9;

const QImg = createComponent({
  name: 'QImg',

  props: {
    ...useRatioProps,

    src: String,
    srcset: String,
    sizes: String,

    alt: String,
    crossorigin: String,
    decoding: String,
    referrerpolicy: String,

    draggable: Boolean,

    loading: {
      type: String,
      default: 'lazy'
    },
    fetchpriority: {
      type: String,
      default: 'auto'
    },
    width: String,
    height: String,
    initialRatio: {
      type: [ Number, String ],
      default: defaultRatio
    },

    placeholderSrc: String,

    fit: {
      type: String,
      default: 'cover'
    },
    position: {
      type: String,
      default: '50% 50%'
    },

    imgClass: String,
    imgStyle: Object,

    noSpinner: Boolean,
    noNativeMenu: Boolean,
    noTransition: Boolean,

    spinnerColor: String,
    spinnerSize: String
  },

  emits: [ 'load', 'error' ],

  setup (props, { slots, emit }) {
    const naturalRatio = ref(props.initialRatio);
    const ratioStyle = useRatio(props, naturalRatio);

    let loadTimer = null, isDestroyed = false;

    const images = [
      ref(null),
      ref(getPlaceholderSrc())
    ];

    const position = ref(0);

    const isLoading = ref(false);
    const hasError = ref(false);

    const classes = computed(() =>
      `q-img q-img--${ props.noNativeMenu === true ? 'no-' : '' }menu`
    );

    const style = computed(() => ({
      width: props.width,
      height: props.height
    }));

    const imgClass = computed(() =>
      `q-img__image ${ props.imgClass !== void 0 ? props.imgClass + ' ' : '' }`
      + `q-img__image--with${ props.noTransition === true ? 'out' : '' }-transition`
    );

    const imgStyle = computed(() => ({
      ...props.imgStyle,
      objectFit: props.fit,
      objectPosition: props.position
    }));

    watch(() => getCurrentSrc(), addImage);

    function getCurrentSrc () {
      return props.src || props.srcset || props.sizes
        ? {
            src: props.src,
            srcset: props.srcset,
            sizes: props.sizes
          }
        : null
    }

    function getPlaceholderSrc () {
      return props.placeholderSrc !== void 0
        ? { src: props.placeholderSrc }
        : null
    }

    function addImage (imgProps) {
      if (loadTimer !== null) {
        clearTimeout(loadTimer);
        loadTimer = null;
      }

      hasError.value = false;

      if (imgProps === null) {
        isLoading.value = false;
        images[ position.value ^ 1 ].value = getPlaceholderSrc();
      }
      else {
        isLoading.value = true;
      }

      images[ position.value ].value = imgProps;
    }

    function onLoad ({ target }) {
      if (isDestroyed === true) { return }

      if (loadTimer !== null) {
        clearTimeout(loadTimer);
        loadTimer = null;
      }

      naturalRatio.value = target.naturalHeight === 0
        ? 0.5
        : target.naturalWidth / target.naturalHeight;

      waitForCompleteness(target, 1);
    }

    function waitForCompleteness (target, count) {
      // protect against running forever
      if (isDestroyed === true || count === 1000) { return }

      if (target.complete === true) {
        onReady(target);
      }
      else {
        loadTimer = setTimeout(() => {
          loadTimer = null;
          waitForCompleteness(target, count + 1);
        }, 50);
      }
    }

    function onReady (img) {
      if (isDestroyed === true) { return }

      position.value = position.value ^ 1;
      images[ position.value ].value = null;
      isLoading.value = false;
      hasError.value = false;
      emit('load', img.currentSrc || img.src);
    }

    function onError (err) {
      if (loadTimer !== null) {
        clearTimeout(loadTimer);
        loadTimer = null;
      }

      isLoading.value = false;
      hasError.value = true;
      images[ position.value ].value = null;
      images[ position.value ^ 1 ].value = getPlaceholderSrc();
      emit('error', err);
    }

    function getImage (index) {
      const img = images[ index ].value;

      const data = {
        key: 'img_' + index,
        class: imgClass.value,
        style: imgStyle.value,
        crossorigin: props.crossorigin,
        decoding: props.decoding,
        referrerpolicy: props.referrerpolicy,
        height: props.height,
        width: props.width,
        loading: props.loading,
        fetchpriority: props.fetchpriority,
        'aria-hidden': 'true',
        draggable: props.draggable,
        ...img
      };

      if (position.value === index) {
        data.class += ' q-img__image--waiting';
        Object.assign(data, { onLoad, onError });
      }
      else {
        data.class += ' q-img__image--loaded';
      }

      return h(
        'div',
        { class: 'q-img__container absolute-full', key: 'img' + index },
        h('img', data)
      )
    }

    function getContent () {
      if (isLoading.value !== true) {
        return h('div', {
          key: 'content',
          class: 'q-img__content absolute-full q-anchor--skip'
        }, hSlot(slots[ hasError.value === true ? 'error' : 'default' ]))
      }

      return h('div', {
        key: 'loading',
        class: 'q-img__loading absolute-full flex flex-center'
      }, (
        slots.loading !== void 0
          ? slots.loading()
          : (
              props.noSpinner === true
                ? void 0
                : [
                    h(QSpinner, {
                      color: props.spinnerColor,
                      size: props.spinnerSize
                    })
                  ]
            )
      ))
    }

    {
      {
        addImage(getCurrentSrc());
      }

      onBeforeUnmount(() => {
        isDestroyed = true;

        if (loadTimer !== null) {
          clearTimeout(loadTimer);
          loadTimer = null;
        }
      });
    }

    return () => {
      const content = [];

      if (ratioStyle.value !== null) {
        content.push(
          h('div', { key: 'filler', style: ratioStyle.value })
        );
      }

      if (hasError.value !== true) {
        if (images[ 0 ].value !== null) {
          content.push(getImage(0));
        }

        if (images[ 1 ].value !== null) {
          content.push(getImage(1));
        }
      }

      content.push(
        h(Transition, { name: 'q-transition--fade' }, getContent)
      );

      return h('div', {
        class: classes.value,
        style: style.value,
        role: 'img',
        'aria-label': props.alt
      }, content)
    }
  }
});

export { QImg };
