<script setup lang="ts">
import { reactive, onMounted } from 'vue';
import { useQuasar } from 'quasar';
import { cloneDeep, isEmpty, omit } from 'src/common/utils';
import nestedDraggable from './element/nested.vue';
import { ComDialogTip } from 'src/components';

const $q = useQuasar();

const SpcGroupItem = {
  show: true,
  title: null,
  children: [],
};
const data = [
  {
    title: '1',
    children: [
      {
        title: '1-1',
        children: [],
      },
      {
        title: '1-2',
        children: [],
      },
      {
        title: '1-3',
        children: [],
      },
    ],
  },
  {
    title: '2',
    children: [],
  },
];

const state = reactive({
  originalData: [] as any[],
  list: [] as any[],
  itemKey: 'key',
  childrenKey: 'children',
  labelKey: 'title',
  dataStacks: [] as any,
});

onMounted(() => {
  initData(data);
});

function initData(data: any) {
  state.originalData = data;
  const _data = cloneDeep(data);
  handleData(_data);
  state.list = _data;
  pushDataToStacks();
  // console.log('state.list', state.list);
}

function pushDataToStacks() {
  state.dataStacks.push({
    data: cloneDeep(state.list),
  });
}

function handleData(data: any, key = state.childrenKey, before = 0) {
  let index = 0;
  data.map((item: any) => {
    let indexstr;
    if (before) {
      indexstr = String(before) + '-' + String(index);
    } else {
      indexstr = String(index);
    }

    if (isEmpty(item.show)) {
      item.show = true;
    }
    item['test_index'] = indexstr;
    item[state.itemKey] = indexstr;
    if (data.length - 1 === index) {
      item.lastChild = true;
    } else {
      item.lastChild = false;
    }
    index++;

    if (!isEmpty(item[key])) {
      handleData(item[key], key, item['test_index']);
    } else {
      item[key] = [];
    }
  });
}

function handelDel(listdata: any[]) {
  const chiledKey = state.childrenKey;
  let newArr = [] as any[];
  listdata.map((item) => {
    if (!isEmpty(item[chiledKey])) {
      item[chiledKey] = handelDel(item[chiledKey]);
    }
    if (!item['test_delete']) {
      newArr.push(item);
    }
  });
  return newArr;
}

function getTarget(list: any, index: number) {
  const target = list[index];
  const parent = list;
  return { target, parent };
}

function delTestKey(listdata: any[]) {
  const chiledKey = state.childrenKey;
  let seq = 1;
  return listdata.map((item: any) => {
    if (!isEmpty(item[chiledKey])) {
      item[chiledKey] = delTestKey(item[chiledKey]);
    }

    const newObj = omit(item, ['key', 'test_index', 'show', 'lastChild']);
    newObj.seq = seq;
    seq++;
    return newObj;
  });
}

// 查看
function viewData() {
  const data = cloneDeep(state.list);
  const resdata = delTestKey(data);
  console.log('最后处理格式', resdata);
}
// 重置
function onReset() {
  state.dataStacks = [];
  initData(cloneDeep(state.originalData));
}
// 拖拽结束
function dragEnd() {
  handleData(state.list);
  pushDataToStacks();
}
// 添加
function onAdd() {
  let obj = { ...SpcGroupItem } as any;
  obj[state.itemKey] = Date.now();

  state.list.push(obj);
  handleData(state.list);
  pushDataToStacks();
}

// 删除
function delItem(data: any) {
  let msg = '';
  if (!isEmpty(data.children)) {
    msg = '确定删除 ' + <string>data.title + '及其所有子项？';
  } else {
    msg = '确定删除 ' + <string>data.title + '？';
  }
  $q.dialog({
    component: ComDialogTip,
    componentProps: {
      persistent: true,
      text: msg,
      color: 'negative',
    },
  }).onOk(() => {
    data['test_delete'] = true;
    let res = handelDel(state.list);
    handleData(res);
    state.list = res;
    pushDataToStacks();
  });
}
// 同级添加
function addItem(data: any) {
  const key = state.childrenKey;
  const indexList = data['test_index'].split('-');

  let re: any;
  for (let i = 0; i < indexList.length; i++) {
    const item = indexList[i];
    if (i === 0) {
      re = getTarget(state.list, Number(item));
    } else {
      re = getTarget(re.target[key], Number(item));
    }
  }

  let obj = { ...SpcGroupItem } as any;
  obj[state.itemKey] = Date.now();

  re.parent.push(obj);
  handleData(state.list);
  pushDataToStacks();
}
// 子级添加
function addNest(data: any) {
  const key = state.childrenKey;
  const indexList = data['test_index'].split('-');

  let re: any;
  for (let i = 0; i < indexList.length; i++) {
    const item = indexList[i];
    if (i === 0) {
      re = getTarget(state.list, Number(item));
    } else {
      re = getTarget(re.target[key], Number(item));
    }
  }

  let obj = { ...SpcGroupItem } as any;
  obj[state.itemKey] = Date.now();

  re.target[key].push(obj);
  handleData(state.list);
  pushDataToStacks();
}
// 撤销
function onUndo() {
  const lastindex = state.dataStacks.length - 2;
  const lastdata = state.dataStacks[lastindex];
  state.list = cloneDeep(lastdata.data);
  state.dataStacks.splice(lastindex + 1, 1);
}
</script>
<template>
  <div class="box">
    <div class="actions">
      <q-btn unelevated color="primary" label="查看" @click="viewData" />
      <q-btn unelevated color="primary" label="重置" @click="onReset" />
      <q-btn unelevated color="primary" label="添加" @click="onAdd" />
      <q-btn
        unelevated
        color="primary"
        label="撤销"
        @click="onUndo"
        :disable="state.dataStacks.length < 2"
      />
    </div>
    <div class="tree-box">
      <nested-draggable
        :tasks="state.list"
        :item-key="state.itemKey"
        :children-key="state.childrenKey"
        :label-key="state.labelKey"
        @onEnd="dragEnd"
        @addItem="addItem"
        @addNest="addNest"
        @delItem="delItem"
      />
    </div>
  </div>
</template>

<style lang="scss" scoped>
.actions {
  padding: 20px 10px 10px 20px;
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  align-items: center;
  column-gap: 10px;
}
.tree-box {
  transform: translateX(-20px);
}
</style>
