// Silence may be golden, but sometimes words paint the canvas of understanding.
const LinksyDataTable = {
  name: "DataTable",
  props: {
    columns: {
      type: Array,
      required: true,
    },
    data: {
      type: Array,
      default: [],
    },

    loading: Boolean,
    hideHeader: Boolean,

    selectableRows: {
      type: Boolean,
      default: false,
    },

    expandableRows: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      rowsMeta: [],
      columnsMeta: [],
    };
  },
  computed: {
    nColspan: {
      get() {
        return this.columns.length + (this.selectableRows ? 1 : 0);
      },
    },
    checked: {
      get() {
        return (
          this.rowsMeta.length > 0 && this.rowsMeta.every((e) => e?.selected)
        );
      },
    },
  },
  watch: {
    data: {
      deep: true,
      handler(val) {
        this.rowsMeta = val.map((e) => ({ selected: false }));
      },
    },
  },
  methods: {
    getChildRef() {
      return this.$refs.tableRef;
    },
    selectAll() {
      this.rowsMeta = this.rowsMeta.map((e) => ({ selected: !this.checked }));

      // Emit event when all rows are selected
      this.$emit("onAllRowsSelected");
    },
    getRowColumnValue(column, item, index) {
      let value = null;
      if (column.selector) {
        value = item[column.selector];
      }

      if (column.format) {
        value = column.format(item, index);
      }

      return value;
    },
    onColumnClicked(column, index) {
      if (column.sortable) {
        const sortDirection = this.columnsMeta[index].sortDirection;
        this.columnsMeta[index].sortDirection =
          !sortDirection || sortDirection === "desc" ? "asc" : "desc";

        this.$emit("onSort", index, this.columnsMeta[index].sortDirection);
      }
    },
    onRowClicked(row, index) {
      this.$emit("onRowClicked", row, index);
    },
    onRowSelected(row, index) {
      this.rowsMeta[index].selected = !this.rowsMeta[index].selected;

      // Emit event when a row is selected or unselected
      this.$emit("onRowSelected", row, index);
    },
  },
  template: `
    <div class="linksy-datatable overflow-auto rounded">
        <div class="linksy-datatable-table">
            <table class="shadow" ref="tableRef">
                <thead v-if="!hideHeader">
                    <tr>
                        <td v-if="selectableRows" width="20">
                            <input type="checkbox" :checked="checked" @change="selectAll" />
                        </td>
                        <td
                            v-for="(column, index) in columns"
                            :title="column.title"
                            @click="onColumnClicked(column, index)"
                            :class="[{'sortable clickable': column.sortable}]"
                        >
                            <div>
                                <slot :name="'column-header-'+index" :item="column" :index="index">
                                    {{column.name}}
                                </slot>

                                <div v-if="column.sortable" class="sortable-container">
                                    <i class="fa fa-sort-up" :class="{'active': columnsMeta[index]?.sortDirection === 'asc'}"></i>
                                    <i class="fa fa-sort-down" :class="{'active': columnsMeta[index]?.sortDirection === 'desc'}"></i>
                                </div>
                            </div>
                        </td>
                    </tr>
                </thead>
                <tbody>
                    <tr v-for="(item, index) in data" class="table-row">
                        <td v-if="selectableRows">
                            <input type="checkbox" :checked="rowsMeta[index]?.selected" @change="onRowSelected(item, index)" />
                        </td>
                        <td
                            v-for="(column, columnIndex) in columns"
                            :class="{sortable: column.sortable}"
                            @click="onRowClicked(item, index)"
                        >
                            <slot :name="'column-'+columnIndex" :item="item" :index="index">
                                {{getRowColumnValue(column, item, index)}}
                            </slot>
                        </td>
                    </tr>

                    <tr v-if="data.length < 1 && !loading">
                        <td :colspan="nColspan">
                            <span>Nothing to display</span>
                        </td>
                    </tr>
                </tbody>
            </table>
        </div>

        <div class="linksy-loader" v-if="loading">
            <span>
                <i class="fa fa-spin fa-spinner"></i>
            </span>
        </div>
    </div>
    `,
  beforeMount() {
    this.columnsMeta = this.columns.map((e, i) => {
      const meta = {};
      if (e.sortable) {
        meta.sort = true;
        meta.sortDirection = e.sortDirection;
      }

      return meta;
    });
  },
};
