<template>
  <div
    class="component-general-list"
    :style="{
      height: props.height === 'fill' ? '100%' : props.height === 'static' ? undefined : `${props.height}px`,
    }"
  >
    <AgGridVue
      style="width: 100%; height: 100%"
      class="ag-theme-balham-dark"
      :getRowId="getRowId"
      :getRowHeight="getRowHeight"
      :columnDefs="columnDefs"
      :rowData="list"
      :defaultColDef="defaultColDef"
      @grid-ready="onGridReady"
    />
  </div>
</template>
<script lang="ts"></script>
<script lang="ts" setup>
import type { GeneralListItem, GeneralListItemP2, GeneralListResponse } from "@/defs/API/Nation";
import { getIconPath } from "@/util/getIconPath";
import { inject, ref, watch, type PropType, type Ref, type StyleValue } from "vue";
import { AgGridVue } from "ag-grid-vue3";
import type {
  CellClassParams,
  CellStyle,
  ColDef,
  ColGroupDef,
  ColumnApi,
  GetRowIdParams,
  GridApi,
  GridReadyEvent,
} from "ag-grid-community";
import { getNpcColor } from "@/common_legacy";
import type { BaseWithValueColDefParams, ValueGetterParams } from "ag-grid-community/dist/lib/entities/colDef";
import type { GameConstStore } from "@/GameConstStore";
import { unwrap } from "@/util/unwrap";
import SimpleTooltipCell from "@/gridCellRenderer/SimpleTooltipCell.vue";
import GridTooltipCell, { type GridCellInfo } from "@/gridCellRenderer/GridTooltipCell.vue";
import { formatConnectScore } from "@/utilGame/formatConnectScore";

const props = defineProps({
  list: {
    type: Array as PropType<GeneralListItem[]>,
    required: true,
  },

  height: {
    type: String as PropType<"static" | "fill" | number | `${number}px` | `${number}%`>,
    required: false,
    default: "static",
  },
  env: {
    type: Object as PropType<GeneralListResponse["env"]>,
    required: true,
  },
});

const gameConstStore = unwrap(inject<Ref<GameConstStore>>("gameConstStore"));
//debug

watch(
  () => props.list,
  () => {
    setTimeout(() => {
      //debug
      gridApi.value?.redrawRows();
    }, 0);
  }
);

watch(
  () => props.height,
  (val) => {
    if (val === "static") {
      gridApi.value?.setDomLayout("autoHeight");
    } else {
      gridApi.value?.setDomLayout("normal");
    }
  }
);

const gridApi = ref<GridApi>();
const columnApi = ref<ColumnApi>();

const rowHeight = ref(28);

function getRowId(params: GetRowIdParams): string {
  const genID = (params.data as GeneralListItem).no;
  return `${genID}`;
}

function onGridReady(params: GridReadyEvent) {
  gridApi.value = params.api;
  columnApi.value = params.columnApi;
  if (props.height === "static") {
    params.api.setDomLayout("autoHeight");
  } else {
    params.api.setDomLayout("normal");
  }
  setRowHeight();
}

function setRowHeight() {
  if (!(columnRawDefs.value.icon as GenColDef | undefined)?.hide) {
    rowHeight.value = 64 + 4;
    return;
  }
  rowHeight.value = gridApi.value?.getSizesForCurrentTheme().rowHeight ?? 28;
}

function getRowHeight(): number {
  return rowHeight.value;
}

type headerType =
  | keyof Omit<GeneralListItemP2, "no" | "imgsvr" | "picture" | "lbonus">
  | "stat"
  | "icon"
  | "goldRice"
  | "expDedLv"
  | "specials"
  | "killturnAndConnect"
  | "years";

interface GenValueParams extends BaseWithValueColDefParams {
  data: GeneralListItem;
}

interface GenValueGetterParams extends ValueGetterParams {
  data: GeneralListItem;
}

interface GenColDef extends ColDef {
  field?: headerType;
  valueFormatter?: string | ((params: GenValueParams) => string);
  filterValueGetter?: string | ((params: GenValueGetterParams) => string);
}

interface GenColGroupDef extends ColGroupDef {
  children: (GenColDef | GenColGroupDef)[];
  groupId: headerType;
}

interface GenCellClassParams extends CellClassParams {
  data: GeneralListItem;
}

function naiveCheClassNameFilter(value: string): string {
  const text = value.split("_").pop() ?? "None";
  if (text === "None") {
    return "-";
  }
  return text;
}

function numberFormatter(value: GenValueParams): string {
  return (value.value as number).toLocaleString();
}

const defaultCellClass = ["cell-middle"];
const centerCellClass = [...defaultCellClass, "cell-center"];
const rightAlignClass = [...defaultCellClass, "cell-right"];
const sortableNumber: GenColDef = {
  sortable: true,
  comparator: (a, b) => a - b,
  sortingOrder: ["desc", "asc", null],
  filter: "number",
  cellClass: rightAlignClass,
};
const defaultColDef = ref<ColDef>({
  resizable: true,
  headerClass: "default-cell-header",
  cellClass: centerCellClass,
  floatingFilter: true,
  width: 80,
});

const columnRawDefs = ref<Partial<Record<headerType, GenColDef | GenColGroupDef>>>({
  icon: {
    headerName: "아이콘",
    width: 64 + 16,
    suppressSizeToFit: true,
    resizable: false,
    cellRenderer: (obj: GenValueParams) => {
      const { data: gen } = obj;
      return `<img src="${getIconPath(gen.imgsvr, gen.picture)}" width="64">`;
    },
    pinned: "left",
    lockPosition: true,
  },
  name: {
    headerName: "장수명",
    field: "name",
    pinned: "left",
    sortable: true,
    width: 120,
    sortingOrder: ["asc", "desc", null],
    lockPosition: true,
    cellStyle: (val: GenCellClassParams) => {
      const gen = val.data;
      const style: StyleValue = {
        color: getNpcColor(gen.npc),
      };
      return style as CellStyle;
    },
    cellClass: defaultCellClass,
    filter: true,
  },
  npc: { headerName: "NPC", field: "npc", hide: true },
  stat: {
    groupId: "stat",
    openByDefault: false,
    headerName: "능력치",
    children: [
      {
        headerName: "통|무|지",
        width: 88,

        cellRenderer: (obj: GenValueParams) => {
          const gen = obj.data;
          return `${gen.leadership}|${gen.strength}|${gen.intel}`;
        },
        columnGroupShow: "closed",
      },
      {
        headerName: "통솔",
        field: "leadership",
        ...sortableNumber,
        columnGroupShow: "open",
        width: 60,
        type: "numericColumn",
      },
      {
        headerName: "무력",
        field: "strength",
        ...sortableNumber,
        columnGroupShow: "open",
        width: 60,
      },
      {
        headerName: "지력",
        field: "intel",
        ...sortableNumber,
        columnGroupShow: "open",
        width: 60,
      },
    ],
  },
  officerLevel: {
    headerName: "관직",
    field: "officerLevelText",
    sortable: true,
    comparator: (a, b, c, d) => c.data.officerLevel - d.data.officerLevel,
    cellRenderer: ({ data }: GenValueParams) => {
      if ([2, 3, 4].includes(data.permission)) {
        const dataP2 = data as GeneralListItemP2;
        if (2 <= dataP2.officerLevel && dataP2.officerLevel <= 4) {
          const cityName = gameConstStore.value.cityConst[dataP2.officer_city].name;
          return `${cityName}<br>${dataP2.officerLevelText}`;
        }
      }
      return data.officerLevelText;
    },
    filterValueGetter: ({ data }) => {
      if ([2, 3, 4].includes(data.permission)) {
        const dataP2 = data as GeneralListItemP2;
        if (2 <= dataP2.officerLevel && dataP2.officerLevel <= 4) {
          const cityName = gameConstStore.value.cityConst[dataP2.officer_city].name;
          return `${cityName} ${dataP2.officerLevelText}`;
        }
      }
      return data.officerLevelText;
    },
    filter: true,
    cellClass: centerCellClass,
    width: 70,
  },
  expDedLv: {
    headerName: "명성",
    groupId: "expDedLv",
    width: 70,
    children: [
      {
        headerName: "/계급",
        columnGroupShow: "closed",
        width: 60,
        cellRenderer: ({ data }: GenValueParams) => {
          return `Lv ${data.explevel}<br>${data.dedLevelText}`;
        },
      },
      {
        headerName: "명성",
        field: "explevel",
        width: 60,
        cellRenderer: ({ data }: GenValueParams) => {
          return `Lv ${data.explevel}<br>(${data.honorText})`;
        },
        ...sortableNumber,
        cellClass: centerCellClass,
        columnGroupShow: "open",
      },
      {
        headerName: "계급",
        field: "dedLevelText",
        width: 70,
        cellRenderer: ({ data }: GenValueParams) => {
          return `${data.dedLevelText}<br>(${data.bill.toLocaleString()})`;
        },
        ...sortableNumber,
        cellClass: centerCellClass,
        columnGroupShow: "open",
      },
    ],
  },
  gold: { headerName: "금", field: "gold", ...sortableNumber, valueFormatter: numberFormatter, width: 70 },
  rice: { headerName: "쌀", field: "rice", ...sortableNumber, valueFormatter: numberFormatter, width: 70 },
  crew: {
    headerName: "보유 병력",
    children: [
      {
        headerName: "병종",
        cellRenderer: GridTooltipCell,
        cellRendererParams: {
          cells: ((): GridCellInfo[][] => {
            return [
              [{ target: "crewtype", iActionMap: gameConstStore.value.iActionInfo.crewtype }],
              [{ target: "crew", converter: (value) => [`${value.crew.toLocaleString()}명`, undefined] }],
            ];
          })(),
        },
      },
      {
        headerName: "훈/사",
        width: 60,
        cellRenderer: ({ data }: GenValueParams) => {
          if (data.permission == 0 || data.permission == 1) {
            return "?";
          }
          return `${data.train}<br>${data.atmos}`;
        },
      },
    ],
  },
  specials: {
    headerName: "특성",
    children: [
      {
        headerName: "요약",
        cellRenderer: GridTooltipCell,
        cellRendererParams: {
          cells: ((): GridCellInfo[][] => {
            return [
              [{ target: "personal", iActionMap: gameConstStore.value.iActionInfo.personality }],
              [
                { target: "specialDomestic", iActionMap: gameConstStore.value.iActionInfo.specialDomestic },
                { target: "specialWar", iActionMap: gameConstStore.value.iActionInfo.specialWar },
              ],
            ];
          })(),
        },
        width: 80,
        columnGroupShow: "closed",
      },
      {
        headerName: "성격",
        field: "personal",
        cellRenderer: SimpleTooltipCell,
        cellRendererParams: {
          iActionMap: gameConstStore.value.iActionInfo.personality,
        },
        width: 60,
        sortable: true,
        filter: true,
        columnGroupShow: "open",
      },
      {
        headerName: "내특",
        field: "specialDomestic",
        cellRenderer: SimpleTooltipCell,
        cellRendererParams: {
          iActionMap: gameConstStore.value.iActionInfo.specialDomestic,
        },
        width: 60,
        sortable: true,
        filter: true,
        columnGroupShow: "open",
      },
      {
        headerName: "전특",
        field: "specialWar",
        cellRenderer: SimpleTooltipCell,
        cellRendererParams: {
          iActionMap: gameConstStore.value.iActionInfo.specialWar,
        },
        width: 60,
        sortable: true,
        filter: true,
        columnGroupShow: "open",
      },
    ],
  },
  years: {
    headerName: "연도",
    children: [
      {
        headerName: "요약",
        width: 60,
        cellRenderer: ({ data }: GenValueParams) => {
          return `${data.age}세<br>${data.belong}년`;
        },
        cellClass: centerCellClass,
        columnGroupShow: "closed",
      },
      {
        headerName: "연령",
        field: "age",
        ...sortableNumber,
        valueFormatter: (v: GenValueParams) => `${v.value}세`,
        width: 60,
        cellClass: centerCellClass,
        columnGroupShow: "open",
      },
      {
        headerName: "사관",
        field: "belong",
        ...sortableNumber,
        valueFormatter: (v: GenValueParams) => `${v.value}년`,
        width: 60,
        cellClass: centerCellClass,
        columnGroupShow: "open",
      },
    ],
  },
  reservedCommand: {
    headerName: "명령",
    children: [
      {
        headerName: "단축",
        width: 70,
        cellRenderer: ({ data }: GenValueParams) => {
          if (data.npc >= 2) {
            return "NPC 장수";
          }
          const commandList = data.reservedCommand;
          if (!commandList) {
            return "???";
          }
          return commandList.map(({ action }) => naiveCheClassNameFilter(action)).join("<br>");
        },
        cellStyle: {
          lineHeight: "1em",
          fontSize: "0.85em",
        },
        columnGroupShow: "closed",
      },
      {
        headerName: "전체",
        width: 120,
        cellRenderer: ({ data }: GenValueParams) => {
          if (data.npc >= 2) {
            return "NPC 장수";
          }
          const commandList = data.reservedCommand;
          if (!commandList) {
            return "???";
          }
          return commandList.map(({ brief }) => brief).join("<br>");
        },
        cellStyle: {
          lineHeight: "1em",
          fontSize: "0.85em",
        },
        columnGroupShow: "open",
      },
    ],
  },
  killturnAndConnect: {
    headerName: "기타",
    children: [
      {
        headerName: "삭/벌",
        cellRenderer: ({ data }: GenValueParams) => {
          return `${data.killturn.toLocaleString()}턴<br>${data.connect.toLocaleString()}점`;
        },
        cellClass: rightAlignClass,
        columnGroupShow: "closed",
        width: 70,
      },
      {
        headerName: "삭턴",
        field: "killturn",
        cellRenderer: ({ data }: GenValueParams) => {
          return `${data.killturn.toLocaleString()}턴`;
        },
        ...sortableNumber,
        width: 70,
        columnGroupShow: "open",
      },
      {
        headerName: "벌점",
        field: "connect",
        cellRenderer: ({ data }: GenValueParams) => {
          return `${data.connect.toLocaleString()}점<br>(${formatConnectScore(data.connect)})`;
        },
        ...sortableNumber,
        width: 70,
        columnGroupShow: "open",
      },
    ],
  },
});
setRowHeight();

const columnDefs = ref([...Object.values(columnRawDefs.value)]);

watch(columnRawDefs, (val) => {
  setRowHeight();
  columnDefs.value = [...Object.values(val)];
  gridApi.value?.redrawRows();
});

</script>

<style scoped lang="scss">
.g-tr {
  border-bottom: solid gray 1px;
}

.g-thead-tr {
  position: sticky;
  top: 0px;
  z-index: 5;
}
</style>

<style lang="scss">
.component-general-list {
  .ag-root-wrapper .cell-middle {
    display: flex;
    align-items: center;
  }

  .ag-root-wrapper {
    font-family: "Pretendard", "Apple SD Gothic Neo", "Noto Sans KR", "Malgun Gothic";
    font-size: 14px;
    overflow: auto;
  }

  .ag-root {
    overflow: auto;
  }

  .ag-header {
    position: sticky;
    top: 0;
    z-index: 10;
  }

  .cell-center {
    justify-content: space-around;
    text-align: center;
  }

  .cell-right {
    justify-content: flex-end;
    text-align: right;
  }

  .cell-sp .col {
    min-width: 30px;
  }

  .ag-header-cell,
  .ag-header-group-cell,
  .ag-cell {
    padding-left: 4px;
    padding-right: 4px;
  }

  .ag-header-cell-label,
  .ag-header-group-cell-label {
    justify-content: center;
  }

  .ag-ltr .ag-floating-filter-button {
    margin-left: 2px;
  }

  .ag-rtl .ag-floating-filter-button {
    margin-right: 2px;
  }
}
</style>
