<template>
  <div ref="layoutDom" :style="useStyle" class="sel-grid">
    <slot v-if="show"></slot>
  </div>
</template>

<script lang="ts" setup>
import { computed, Ref, ref, watchEffect, provide, nextTick, getCurrentInstance, onMounted } from 'vue'
import {
  layoutConfigMode,
  xyGridMode,
} from '../types'
import {
  getXYGap,
  calcGrid,
} from './layout'
import { useElementSize } from '@vueuse/core'

const instance: any = getCurrentInstance()
const styled = computed(() => instance?.appContext.config.globalProperties.styled)
defineOptions({
  name: 'SGrid',
})

export interface PropsType {
  rows?: number
  cols?: number
  gap?: Array<number> | number
  auto?: boolean
  xGrid?: number
  yGrid?: number
}

const props = withDefaults(defineProps<PropsType>(),  {
  rows: 0,
  cols: 24,
  gap: () => [ 0, 0 ],
  auto: true,
  xGrid: 0,
  yGrid: 0,
})

const layoutDom = ref()
const { width, height } = useElementSize(layoutDom)
watchEffect(() => {
  if (width.value && height.value) {
    styled.value(layoutDom.value, init())
  }
})

onMounted(() => {
  styled.value(layoutDom.value, init())
})

const useStyle = ref()
const xyGrid: Ref<xyGridMode> = ref({
  xGrid: 0,
  yGrid: 0,
})
const { xGap, yGap } = getXYGap(props.gap)
const xGapV = computed(() => xGap + 'px')
const yGapV = computed(() => yGap + 'px')
const colsV = computed(() => `repeat(${ props.cols }, ${ xyGrid.value.xGrid }px)`)
const rowsV = computed(() => props.rows ? `repeat(${ props.rows }, ${ xyGrid.value.yGrid }px)` : 'auto')

watchEffect(() => {
  if (props.rows && props.cols && props.gap && props.auto && props.xGrid && props.yGrid) {
    init()
  }
})

function init () {
  const style: any = {}
  initXYGrid()
  if (!(width.value && height.value)) return {}
  if (xGapV.value) style.gridColumnGap = xGapV.value
  if (yGapV.value) style.gridRowGap = yGapV.value
  if (colsV.value) style.gridTemplateColumns = colsV.value
  if (rowsV.value !== 'auto' && xyGrid.value.yGrid) style.gridTemplateRows = rowsV.value
  if (xyGrid.value.xGrid) style.gridAutoColumns = `${ xyGrid.value.xGrid }px`
  if (rowsV.value !== 'auto' && xyGrid.value.yGrid) style.gridAutoRows = `${ xyGrid.value.yGrid }px`
  useStyle.value = style
}

provide('xGapV', xGapV)
provide('xyGrid', xyGrid)
const show = ref(false)

async function initXYGrid () {
  if (layoutDom.value) {
    if (props.cols) {
      const { xGrid: x, yGrid: y } = calcGrid({
        width: width.value,
        height: height.value,
      }, props as layoutConfigMode)
      xyGrid.value.xGrid = x
      xyGrid.value.yGrid = y
      await nextTick()
      show.value = true
    }
  }
}

</script>
<style lang="scss">
.sel-grid {
  display: grid;
  position: relative;
}
</style>
