<template>
  <div class="layout-render-wraper">
    <div
      v-for="(row, rowIndex) in pageLayouts"
      :key="rowIndex"
      :style="{
        position: 'relative',
        ...getRowLayoutStyle(pageLayouts, rowIndex, row, 0),
      }"
    >
      <a-row type="flex" :gutter="gutter" style="height: 100%">
        <template v-if="row.cols instanceof Array && row.cols.length">
          <a-col
            v-for="(col, colIndex) in row.cols"
            :key="colIndex"
            :span="col.span"
            :style="{
              height: getColLayoutHeight(row, col),
            }"
          >
            <template v-if="col.rows instanceof Array && col.rows.length">
              <a-row
                v-for="(item, itemIndex) in col.rows"
                :key="itemIndex"
                :style="{
                  ...getRowLayoutStyle(col.rows, itemIndex, item),
                }"
                :gutter="gutter"
                type="flex"
              >
                <a-col
                  v-for="(e, eIndex) in item.cols"
                  :key="eIndex"
                  :span="e.span"
                  :style="{
                    height: getColLayoutHeight(item, e),
                  }"
                >
                  <GridLayout
                    :components="getComponentsByLayout(e)"
                    class="layout-render-content"
                  />
                </a-col>
              </a-row>
            </template>
            <GridLayout
              v-else
              class="layout-render-content"
              :components="getComponentsByLayout(col)"
            />
          </a-col>
        </template>
      </a-row>
    </div>
  </div>
</template>

<script>
import { uniq } from "lodash";
import GridLayout from "./GenerateGrid.vue";

export default {
  components: {
    GridLayout,
  },
  props: {
    layouts: {
      type: Array,
      default: () => [],
    },
    components: {
      type: Array,
      default: () => [],
    },
    gutter: {
      type: Number,
      default: 12,
    },
  },
  data() {
    return {
      pageLayouts: [],
      componentsMap: null,
    };
  },
  watch: {
    layouts: {
      handler(val) {
        this.pageLayouts = [].concat(val);
      },
      immediate: true,
      deep: true,
    },
    components: {
      handler(val) {
        this.componentsMap = new Map();
        val?.forEach((c) => {
          this.componentsMap.set(
            c.layoutKey,
            c.components.map((e, i) => ({
              x: e.x || 0,
              y: e.y || 0,
              w: e.w || 24,
              h: e.h || 10,
              i,
              url: e.url,
            }))
          );
        });
      },
      immediate: true,
      deep: true,
    },
  },
  methods: {
    // 获取布局下的组件集合
    getComponentsByLayout(layout) {
      return this.componentsMap.get(layout.key) || [];
    },
    getColHeight(col) {
      if (col.moveHeight) {
        return col.moveHeight;
      }
      if (col.height) {
        return col.height;
      }
      if (col.rows instanceof Array && col.rows.length) {
        const height = col.rows.reduce((itemPre, item) => {
          const itemHeight = item.cols.reduce((ePre, e) => {
            return ePre + parseInt(e.height, 10);
          }, 0);
          return itemPre + itemHeight;
        }, 0);

        return `${height}%`;
      }
      return "100%";
    },
    getRowLayoutStyle(rows, index, row, level) {
      const fn = (len, i, height, gutter) => {
        const halfGutter = gutter / 2;
        const tmp = {};
        if (len > 1) {
          if (i === 0) {
            tmp.height = `calc(${height} - ${halfGutter}px)`;
          } else if (i === len - 1) {
            tmp.height = `calc(${height} - ${halfGutter}px)`;
            tmp.marginTop = `${gutter}px`;
          } else {
            tmp.marginTop = `${gutter}px`;
            tmp.height = `calc(${height} - ${gutter}px)`;
          }
        } else {
          tmp.height = height;
        }
        return tmp;
      };

      let rowHeight = "100%";
      if (row.cols instanceof Array && row.cols.length) {
        let isPercent = true;
        const colTotalHeight = row.cols.reduce((prev, item, i) => {
          // 判断是百分比还是像素
          const height = this.getColHeight(item);
          if (i === 0 && !height.includes("%")) {
            isPercent = false;
          }
          return prev + parseInt(height, 10);
        }, 0);

        if (isPercent) {
          if (level === 0) {
            rowHeight = `${colTotalHeight / row.cols.length}%`;
          } else {
            rowHeight = `${colTotalHeight}%`;
          }
        } else {
          rowHeight = `${colTotalHeight / row.cols.length}px`;
        }
      }

      return fn(rows.length, index, rowHeight, this.gutter);
    },
    getColLayoutHeight(row, col) {
      const tmp = uniq(row.cols.map((item) => this.getColHeight(item)));

      if (row.cols.length === 1) {
        return "100%";
      }

      if (tmp.length === row.cols.length) {
        return col.height;
      }

      return "100%";
    },
  },
};
</script>

<style lang="less" scoped>
.layout-render {
  &-wraper {
    position: relative;
    width: 100%;
    height: 100%;
    background: #f0f2f5;
  }
  &-content {
    position: relative;
    width: 100%;
    height: 100%;
  }
}
</style>
