<template>
  <div
    class="m-table-draggable overflow-auto"
    :style="{
      'border-color': borderless ? 'transparent' : borderColor,
      'border-width': borderOnContainer,
    }">
    <table
      class="table mb-0"
      :class="{'table-striped': striped}">
      <thead>
        <tr>
          <th
            v-for="(item, headerItemIndex) in headerItems"
            :key="headerItemIndex"
            class="text-nowrap"
            :class="[
              item && item.align ? `text-${item.align}` : null,
            ]"
            :style="{
              'background-color': headerBackgroundColor,
              'border-color': borderless ? 'transparent' : borderColor,
              'color': headerTextColor,
              'z-index': zIndex,
              'border-bottom-width': borderOnHeader,
              'border-left-width': headerItemIndex!==0 ? bordersOnColumns : 0
            }"
            scope="col">
            <slot
              v-if="!$scopedSlots[`header-cell-${headerItemIndex}`]"
              name="header-cells"
              :cell-data="item">
              {{ typeof item ? (typeof item==='object' ? item.text : item) : undefined }}
            </slot>
            <slot
              v-else
              :name="'header-cell-'+headerItemIndex"
              :cell-data="item">
              {{ typeof item ? (typeof item==='object' ? item.text : item) : undefined }}
            </slot>
          </th>
        </tr>
      </thead>
      <tbody>
        <tr
          v-for="(row,rowIndex) in bodyItems"
          :key="rowIndex">
          <!--
            @slot Dynamic slot for all cells in a row of the table body.
            <span class="d-block mt-3">Example: <code>body-row-0</code> will set
            all the cells of the row with index 0</span>
            -->
          <slot
            :name="`body-row-${rowIndex}`"
            :rowData="row"
            :rowStyle="rowStyle(rowIndex)">
            <td
              v-for="(cell,columnIndex) in row"
              :key="columnIndex"
              :class="[
                headerItems[columnIndex] && headerItems[columnIndex].align
                  ? `text-${headerItems[columnIndex].align}`
                  : null
              ]"
              :style="rowStyle(rowIndex, columnIndex)">
              <!--
                @slot Dynamic slot for individual body cell. X is the column and Y is the row.
                <span class="d-block mt-3">Example: <code>body-x0y1</code> will set the slot
                for the cell in the column at index 0 and the row at index 1</span>
                -->
              <slot
                v-if="$scopedSlots[`body-x${columnIndex}y${rowIndex}`]"
                :name="`body-x${columnIndex}y${rowIndex}`"
                :cell-data="cell">
                {{ cell }}
              </slot>

              <!--
                @slot Dynamic slot for all cells in a column of the table body.
                <span class="d-block mt-3">Example: <code>body-column-0</code> will set
                all the cells of the column with index 0</span>
                -->
              <slot
                v-else
                :name="`body-column-${columnIndex}`"
                :cell-data="cell">
                {{ cell }}
              </slot>
            </td>
          </slot>
        </tr>
      </tbody>
    </table>
  </div>
</template>
<script>
/**
 * Table fully customizable by vue props, on mobile keeps the first column fixed as sticky.
 * Easy customization for text colors, backgrounds for header and body cells.
 * <strong><i>Dynamic slots for columns, rows, header and individual cells.</i></strong>
 */
export default {
  name: 'MTableDraggable',
  props: {
    /**
     * The header items
     */
    headerItems: {
      type: Array,
      default: () => [],
    },
    /**
     * The body items as array of vectors
     */
    bodyItems: {
      type: Array,
      default: () => [],
    },
    /**
     * To set the rows with striped colors
     */
    striped: {
      type: Boolean,
      default: true,
    },
    /**
     * The striped color for body rows
     */
    stripedColor: {
      type: String,
      default: '#f4f4f7',
    },
    /**
     * The body text color
     */
    bodyTextColor: {
      type: String,
      default: 'inherit',
    },
    /**
     * The table background color
     */
    backgroundColor: {
      type: String,
      default: '#fff',
    },
    /**
     * The header text color
     */
    headerTextColor: {
      type: String,
      default: 'inherit',
    },
    /**
     * The header background color
     */
    headerBackgroundColor: {
      type: String,
      default: '#fff',
    },
    /**
     * The z-index for first column items on mobile
     */
    zIndex: {
      type: Number,
      default: 100,
    },
    /**
     * The borders color
     */
    borderColor: {
      type: String,
      default: '#e7e7e7',
    },
    /**
     * The border width by css value
     */
    borderWidth: {
      type: String,
      required: false,
      default: '1px',
    },
    /**
     * To set borders transparent
     */
    borderless: {
      type: Boolean,
      default: false,
    },
    /**
     * Borders to show separated with pipes |
     * <strong>Options:</strong> <code>header|columns|rows|container</code>
     */
    borders: {
      type: String,
      required: false,
      default: 'header|columns',
    },
  },
  computed: {
    /**
     * The odd row color
     * If striped is true then stripedColor will be the row color.
     */
    oddRowColor() {
      if (this.striped) return this.stripedColor;
      return this.backgroundColor;
    },
    /**
     * Borders on columns
     */
    bordersOnColumns() {
      return this.borders.split('|').indexOf('columns') > -1 ? this.borderWidth : 0;
    },
    /**
     * Borders on rows
     */
    bordersOnRows() {
      return this.borders.split('|').indexOf('rows') > -1 ? this.borderWidth : 0;
    },
    /**
     * Borders on header bottom
     */
    borderOnHeader() {
      return this.borders.split('|').indexOf('header') > -1 ? this.borderWidth : 0;
    },
    /**
     * Borders on container
     */
    borderOnContainer() {
      return this.borders.split('|').indexOf('container') > -1 ? this.borderWidth : 0;
    },
  },
  methods: {
    /**
     * Returns the row style based by properties customization, row and cell index
     */
    rowStyle(rowIndex, cellIndex) {
      return {
        'background-color': rowIndex % 2 === 0 ? this.oddRowColor : this.backgroundColor,
        'border-color': this.borderless ? 'transparent' : this.borderColor,
        color: this.bodyTextColor,
        'z-index': this.zIndex,
        'border-left-width': cellIndex !== 0 ? this.bordersOnColumns : 0,
        'border-top-width': rowIndex !== 0 ? this.bordersOnRows : 0,
      };
    },
  },
};
</script>

<style lang="scss" scoped>

.m-table-draggable {
  border-style: solid;

  table {
    color: inherit;
  }

  th:first-child,
  td:first-child  {
    left: 0;
  }

  th {
    border-top: none;
    border-bottom-style: solid;

    + th {
      border-left-style: solid;
    }
  }

  td {
    border-top-style: solid;
    border-top-width: 0;

    + td {
      border-left-style: solid;
    }
  }

}

@media (max-width: 767.98px) {
  .m-table-draggable {
    th:first-child,
    td:first-child {
      position: sticky;
    }

    th:first-child::before,
    td:first-child::before {
      position: absolute;
      top: 0;
      left: calc(100% - 1px);

      width: 1px;
      height: 100%;

      content: "";

      box-shadow: 4px 0 12px rgba(0, 0, 0, .6);
    }
  }
}
</style>
