import { resolveDirective as _resolveDirective, createVNode as _createVNode } from "vue";
import "./VImg.sass"; // Vue

import { computed, defineComponent, h, nextTick, onBeforeMount, ref, vShow, watch, withDirectives } from 'vue'; // Components

import { VResponsive } from "../VResponsive/index.mjs"; // Directives

import intersect from "../../directives/intersect/index.mjs";
// Composables
import { makeTransitionProps } from "../../composables/transition.mjs"; // Utils

import { makeProps, maybeTransition, SUPPORTS_INTERSECTION, useDirective, useRender } from "../../util/index.mjs"; // Types

export default defineComponent({
  name: 'VImg',
  props: makeProps({
    aspectRatio: [String, Number],
    alt: String,
    cover: Boolean,
    eager: Boolean,
    lazySrc: String,
    options: {
      type: Object,
      // For more information on types, navigate to:
      // https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
      default: () => ({
        root: undefined,
        rootMargin: undefined,
        threshold: undefined
      })
    },
    position: {
      type: String,
      default: 'center center'
    },
    sizes: String,
    src: {
      type: [String, Object],
      default: ''
    },
    srcset: String,
    ...makeTransitionProps()
  }),
  emits: ['loadstart', 'load', 'error'],

  setup(props, {
    emit,
    slots
  }) {
    const currentSrc = ref(''); // Set from srcset

    const image = ref();
    const state = ref('idle');
    const naturalWidth = ref();
    const naturalHeight = ref();
    const normalisedSrc = computed(() => {
      return props.src && typeof props.src === 'object' ? {
        src: props.src.src,
        srcset: props.srcset || props.src.srcset,
        lazySrc: props.lazySrc || props.src.lazySrc,
        aspect: Number(props.aspectRatio || props.src.aspect)
      } : {
        src: props.src,
        srcset: props.srcset,
        lazySrc: props.lazySrc,
        aspect: Number(props.aspectRatio || 0)
      };
    });
    const aspectRatio = computed(() => {
      return normalisedSrc.value.aspect || naturalWidth.value / naturalHeight.value || 0;
    });
    watch(() => props.src, () => {
      init(state.value !== 'idle');
    }); // TODO: getSrc when window width changes

    onBeforeMount(() => init());

    function init(isIntersecting) {
      // If the current browser supports the intersection
      // observer api, the image is not observable, and
      // the eager prop isn't being used, do not load
      if (SUPPORTS_INTERSECTION && !isIntersecting && !props.eager) return;
      state.value = 'loading';
      nextTick(() => {
        var _image$value;

        emit('loadstart', ((_image$value = image.value) == null ? void 0 : _image$value.currentSrc) || normalisedSrc.value.src);
        if (!aspectRatio.value) pollForSize(image.value);
        getSrc();
      });

      if (normalisedSrc.value.lazySrc) {
        const lazyImg = new Image();
        lazyImg.src = normalisedSrc.value.lazySrc;
        pollForSize(lazyImg, null);
      }
    }

    function onLoad() {
      var _image$value2;

      getSrc();
      state.value = 'loaded';
      emit('load', ((_image$value2 = image.value) == null ? void 0 : _image$value2.currentSrc) || normalisedSrc.value.src);
    }

    function onError() {
      var _image$value3;

      state.value = 'error';
      emit('error', ((_image$value3 = image.value) == null ? void 0 : _image$value3.currentSrc) || normalisedSrc.value.src);
    }

    function getSrc() {
      const img = image.value;
      if (img) currentSrc.value = img.currentSrc || img.src;
    }

    function pollForSize(img, timeout = 100) {
      const poll = () => {
        const {
          naturalHeight: imgHeight,
          naturalWidth: imgWidth
        } = img;

        if (imgHeight || imgWidth) {
          naturalWidth.value = imgWidth;
          naturalHeight.value = imgHeight;
        } else if (!img.complete && state.value === 'loading' && timeout != null) {
          setTimeout(poll, timeout);
        } else if (img.currentSrc.endsWith('.svg') || img.currentSrc.startsWith('data:image/svg+xml')) {
          naturalWidth.value = 1;
          naturalHeight.value = 1;
        }
      };

      poll();
    }

    const containClasses = computed(() => ({
      'v-img__img--cover': props.cover,
      'v-img__img--contain': !props.cover
    }));

    const __image = computed(() => {
      if (!normalisedSrc.value.src || state.value === 'idle') return;
      const img = h('img', {
        class: ['v-img__img', containClasses.value],
        src: normalisedSrc.value.src,
        srcset: normalisedSrc.value.srcset,
        sizes: props.sizes,
        ref: image,
        onLoad,
        onError
      });
      const sources = slots.sources == null ? void 0 : slots.sources();
      return maybeTransition(props, {
        appear: true
      }, withDirectives(sources ? _createVNode("picture", {
        "class": "v-img__picture"
      }, [sources, img]) : img, [[vShow, state.value === 'loaded']]));
    });

    const __preloadImage = computed(() => {
      return maybeTransition(props, {}, normalisedSrc.value.lazySrc && state.value !== 'loaded' ? _createVNode("img", {
        "class": ['v-img__img', 'v-img__img--preload', containClasses.value],
        "src": normalisedSrc.value.lazySrc,
        "alt": ""
      }, null, 10, ["src"]) : undefined);
    });

    const __placeholder = computed(() => {
      if (!slots.placeholder) return;
      const placeholder = state.value === 'loading' || state.value === 'error' && !slots.error ? _createVNode("div", {
        "class": "v-img__placeholder"
      }, [slots.placeholder()]) : undefined;
      return maybeTransition(props, {
        appear: true
      }, placeholder);
    });

    const __error = computed(() => {
      if (!slots.error) return;
      const error = state.value === 'error' ? _createVNode("div", {
        "class": "v-img__error"
      }, [slots.error()]) : undefined;
      return maybeTransition(props, {
        appear: true
      }, error);
    });

    useRender(() => withDirectives(_createVNode(VResponsive, {
      "class": "v-img",
      "aspectRatio": aspectRatio.value,
      "aria-label": props.alt,
      "role": props.alt ? 'img' : undefined
    }, {
      additional: () => [__image.value, __preloadImage.value, __placeholder.value, __error.value],
      default: slots.default,
      _: 1
    }, 8, ["aspectRatio", "aria-label", "role"]), [useDirective(intersect, {
      value: {
        handler: init,
        options: props.options
      },
      modifiers: {
        once: true
      }
    })]));
    return {
      currentSrc,
      image,
      state,
      naturalWidth,
      naturalHeight
    };
  }

});
//# sourceMappingURL=VImg.mjs.map