import { Canvas, Meta, Story } from '@storybook/addon-docs';
import { CvDataTable } from '.';
import CvDataTableHeading from './CvDataTableHeading.vue';
import CvDataTableRow from "./CvDataTableRow.vue";
import CvDataTableCell from "./CvDataTableCell.vue";
import CvDataTableAction from "./CvDataTableAction.vue";
import CvDataTableSkeleton from "./CvDataTableSkeleton.vue";
import CvButton from '../CvButton/CvButton.vue'
import { sbCompPrefix, storySourceCode } from '../../global/storybook-utils';
import { action } from '@storybook/addon-actions';
import { Terminal16 as CompileIcon, Debug16 as DebugIcon, Chip16 as EmbedIcon,
  TrashCan16 as TrashCanIcon} from '@carbon/icons-vue'
import { ref } from 'vue';
const testData = ref([
  { index:"0", name:"Java", year:1995, oo:"Yes", purpose:"Applications", standard:"Java Language Specification", desc: "As of September 2022, Java 19 is the latest version, while Java 17, 11 and 8 are the current long-term support (LTS) versions."},
  { index:"1", name:"COBOL", year:1959, oo:"Yes", purpose:"Business applications", standard:"COBOL 2014", desc: "COBOL statements have an English-like syntax, which was designed to be self-documenting and highly readable."},
  { index:"2", name:"Pascal", year:1970, oo:"No", purpose:"Applications", standard:"None", desc: "Pascal was developed on the pattern of the ALGOL 60 language."},
  { index:"3", name:"Ada", year:1980, oo:"Yes", purpose:"US DoD projects", standard:"Ada 2012 TC1", desc: "Ada was named after Ada Lovelace (1815–1852), who has been credited as the first computer programmer."},
  { index:"4", name:"BASIC", year:1964, oo:"No", purpose:"Education", standard:"ANSI", desc: "BASIC declined in popularity in the 1990s"},
  { index:"5", name:"C++", year:1985, oo:"Yes", purpose:"Systems programming", standard:"ISO/IEC 2017", desc: "C++ is standardized by the International Organization for Standardization (ISO), with the latest standard version ratified and published by ISO in December 2020 as ISO/IEC 14882:2020 (informally known as C++20)."},
  { index:"6", name:"Fortran", year:1957, oo:"No", purpose:"Engineering applications", standard:"ANSI", desc: "Fortran was originally developed by IBM in the 1950s for scientific and engineering applications, and subsequently came to dominate scientific computing."},
  { index:"7", name:"Go", year:2009, oo:"Maybe", purpose:"Networked applications", standard:"Go Spec", desc: "Go's designers were primarily motivated by their shared dislike of C++."},
]);
const sortOpts = ref({index: "0", order: "none", name: "name"})
function sortTestData(opts) {
  action('sort')(opts)
  sortOpts.value = opts
  if (opts.order === 'none')
    return testData.value.sort((a, b) => a.index.localeCompare(b.index, 'en', { sensitivity: 'base' }));
  let direction = 1
  if (opts.order === 'descending') direction = -1
  if (opts.name === 'name')
    return testData.value.sort((a, b) => direction * a.name.localeCompare(b.name, 'en', { sensitivity: 'base' }));
  else if (opts.name === 'year')
    return testData.value.sort((a, b) => direction * (a.year - b.year));
}
// duplicate the test data
const originalTestData = ref(JSON.parse(JSON.stringify(testData.value)))
const searchOpts = ref("")
function searchTestData(opts) {
  action('search')(opts)
  searchOpts.value = opts
  if (!opts) testData.value = JSON.parse(JSON.stringify(originalTestData.value))
  else testData.value = originalTestData.value.filter(data => data.name.indexOf(opts) > -1)
  return sortTestData(sortOpts.value)
}
const selectedRows = ref(["COBOL"])

<Meta title={`${sbCompPrefix}/CvDataTable`} component={CvDataTable} />

export const Template = args => ({
// Components used in your story `template` are defined in the `components` object
components: {
  CvDataTable,
  CvDataTableHeading,
  CvDataTableRow,
  CvDataTableCell,
  CvDataTableAction,
  CompileIcon,
  DebugIcon,
  EmbedIcon,
  CvButton,
  CvDataTableSkeleton,
},
// The story's `args` need to be mapped into the template through the `setup()` method
setup() {
  return {
    args: {...args,
      useActions: undefined,
      useBatchActions: undefined,
      useHelperTextSlot: undefined,
      template: undefined},
    trashIcon: TrashCanIcon,
    onSort: sortTestData,
    onSearch: searchTestData,
    onRowSelectChange: action('row-select-change'),
    onRowSelectChanges: action('row-select-changes'),
    onOverflowMenuClick: action('overflow-menu-click'),
    onVmodel: action('v-model'),
    onRowExpanded: action('row-expanded'),
    onPagination: action('pagination'),
    onAction1: action('compile'),
    onAction2: action('debug'),
    onAction3: action('firmware'),
    onDelete: action('delete'),
    useActions: args.useActions,
    useBatchActions: args.useBatchActions,
    useHelperTextSlot: args.useHelperTextSlot,
    usePagination: args.usePagination,
    skeletonRows: args.skeletonRows,
    skeletonCols: args.skeletonCols,
    skeletonTitle: args.title,
    skeletonHelper: args.helperText,
    testData,
    originalTestData,
    searchOpts,
    selectedRows
    };
},
// And then the `args` are bound to your component with `v-bind="args"`
template: args.template,
});
const defaultTemplate = `
<cv-data-table v-bind="args"
  @search="onSearch"
  @sort="onSort"
  @row-select-change="onRowSelectChange"
  @row-select-changes="onRowSelectChanges"
  @overflow-menu-click="onOverflowMenuClick"
  @row-expanded="onRowExpanded"
  @pagination="onPagination"
  :pagination="usePagination"
  :initialSearchValue="searchOpts"
  >
  <template v-if="useBatchActions" #batch-actions>
    <cv-button :icon="trashIcon" @click="onDelete">Delete</cv-button>
  </template>
  <template v-if="useActions" #actions>
    <cv-data-table-action @click="onAction1" aria-label="compile" alt="compile">
      <compile-icon>
        <title>Compile</title>
      </compile-icon>
    </cv-data-table-action>
    <cv-data-table-action @click="onAction2" aria-label="debug" alt="debug">
      <debug-icon>
        <title>Debug</title>
      </debug-icon>
    </cv-data-table-action>
    <cv-data-table-action @click="onAction3" aria-label="firmware" alt="firmware">
      <embed-icon>
        <title>Install Firmware</title>
      </embed-icon>
    </cv-data-table-action>
  </template>
  <template #headings>
    <cv-data-table-heading id="sb-name" heading="Name" name="name" sortable order="ascending"/>
    <cv-data-table-heading id="sb-year" heading="Year" name="year" sortable/>
    <cv-data-table-heading id="sb-oo" heading="Object Oriented"/>
    <cv-data-table-heading id="sb-purpose" heading="Purpose" />
    <cv-data-table-heading id="sb-standard" heading="Standard" />
  </template>
  <template #data>
    <cv-data-table-row v-for="row in testData" :id="row.name" :key="row.name" :value="row.name">
      <cv-data-table-cell>{{row.name}}</cv-data-table-cell>
      <cv-data-table-cell>{{row.year}}</cv-data-table-cell>
      <cv-data-table-cell>{{row.oo}}</cv-data-table-cell>
      <cv-data-table-cell>{{row.purpose}}</cv-data-table-cell>
      <cv-data-table-cell>{{row.standard}}</cv-data-table-cell>
      <!-- Add optional expanding data here -->
    </cv-data-table-row>
  </template>
</cv-data-table>
`;
const expandingRowsTemplate = defaultTemplate.replace(
  "<!-- Add optional expanding data here -->",
  `<template #expandedContent>{{row.desc}}</template>`)
  .replace('@search="onSearch"', ':expandable="true"')
  .replace('testData', 'originalTestData')
const skeletonTemplate = `
<cv-data-table-skeleton
  :columns="skeletonCols"
  :rows="skeletonRows"
  :title="skeletonTitle"
  :helperText="skeletonHelper">
  <template v-if="useBatchActions" #batch-actions>
    <cv-button :icon="trashIcon" @click="onDelete">Delete</cv-button>
  </template>
  <template v-if="useActions" #actions>
    <cv-data-table-action @click="onAction1" aria-label="compile" alt="compile">
      <compile-icon>
        <title>Compile</title>
      </compile-icon>
    </cv-data-table-action>
  </template>
</cv-data-table-skeleton>
`;
const vModelTemplate = defaultTemplate
  .replace('@search="onSearch"', 'v-model:rows-selected="selectedRows"')
  .replace('@row-select-change="onRowSelectChange"', '@update:rows-selected="onVmodel"')
  .replace('@row-select-changes="onRowSelectChanges"','')
  .replace('testData', 'originalTestData') + `
<div style="margin-top:1rem; background-color: #888888;  padding:1rem"><div style="font-size: 150%">Sample interaction</div>
<select name="programming-languages" id="programming-languages" v-model="selectedRows" multiple>
  <option v-for="l in originalTestData" :id="l.name" :key="l.name" :value="l.name">{{l.name}}</option>
</select>
<div>selections: {{ selectedRows }} </div>
</div>`

# CvDataTable

**Usage:**
- Sorting, filtering and pagination are the responsibility of the component user. This component raises events to facilitate this.
  For example the test data is sorted like this but this is very specific to this data. Users will need to provide their own sort and filtering.
  ```javascript
  // sort example
  const sortOpts = ref({index: "0", order: "none", name: "name"})
  function sortTestData(opts) {
    sortOpts.value = opts // remember this so it can be used in filtering
    if (opts.order === 'none')
      return testData.value.sort((a, b) => a.index.localeCompare(b.index, 'en', { sensitivity: 'base' }));
    let direction = 1
    if (opts.order === 'descending') direction = -1
    if (opts.name === 'name')
      return testData.value.sort((a, b) => direction * a.name.localeCompare(b.name, 'en', { sensitivity: 'base' }));
    else if (opts.name === 'year')
      return testData.value.sort((a, b) => direction * (a.year - b.year));
  }
  // filter example
  function searchTestData(opts) {
    if (!opts) testData.value = allData.value
    else testData.value = allData.value.filter(data => data.name.indexOf(opts) > -1)
    return sortTestData(sortOpts.value)
  }
  ```
- The search bar appears only if the search event is listened for.
- If your table has expanding rows, you MUST set the `expandable` property on CvTable to `true`. `<cv-table :expandable="true" ...`

**Row attributes:**
- aria-label-for-batch-checkbox: Aria label for batch checkbox. default 'Select row N for batch action'.
- aria-label-expand-row: Aria label for expanding row expansion button. default: 'Expand current row'
- aria-label-collapse-row: Aria label for expanding row collapse button. default: 'Collapse current row'
- expanded: initial state of the expanded row
- value: this is the value assign to the checkbox for tables with batch actions.

**Migration notes:**

- Default batch cancel label changed from "cancel" to "Cancel"
- The sort event now returns an additional value "name" for example
`{index: "1", order: "ascending", name: "year"}`. You can set the name value as a property on the
`cv-data-table-heading` element
- The `search` emit is not defined on the component and so your IDE likely will not suggest a type-ahead
completion for it. See [discussion](https://github.com/vuejs/core/issues/3432) for the reason for this. The
`search` emit is still emitted it is just not defined directly on the component.
- The React does not seem to have an "autoWidth" property. It is still supported here but likely the better choice is `staticWidth`.
- Row sizes in the React component are 'xs', 'sm', 'md', 'lg', & 'xl'. The rowSizes from Vue2 are still supported.
- If you were using something like `this.$refs.tableEditPath.batchActive = true` to force batch actions to show even
when no items were select, please now use the new property `stickyBatchActive`.

<Canvas>
  <Story
    name="Default"
    parameters={{
      controls: { exclude: ['default',
          'template',
          'overflow-menu-click',
          'pagination',
          'row-expanded',
          'row-select-change',
          'row-select-changes',
          'search',
          'sort',
          'actions',
          'batch-actions',
          'data',
          'headings',
          'helper-text',
          'items-selected',
          'of-n-pages',
          'range-text',
          'skeleton',
          'update:rowsSelected',
        ] },
      docs: { source: { code: storySourceCode(defaultTemplate, Template.args) } },
    }}
    args={{
      template: defaultTemplate,
      title: 'Table title: Programming Languages',
      helperText: 'Table helper text',
      useActions: false,
      useBatchActions: false,
      usePagination: true
    }}
    argTypes={{
      rowSize: { control: 'select', default: 'lg', options: ['xs', 'sm', 'md', 'lg', 'xl'] },
      rowsSelected: { control: 'multi-select',  options: ['Java', 'COBOL', 'C++'] },
      useBatchActions: { description: "To use batch actions you should assign a usable `id` to each row. i.e. `<cv-data-table-row :id=\"item.id\" ...` This `id` value is passed to the row selection events." }
    }}
  >
    {Template.bind({})}
  </Story>
</Canvas>

<Canvas>
  <Story
    name="Expanding rows"
    parameters={{
      controls: { include: [ "helperText", "title", "hasExpandAll"] },
      docs: { source: { code: storySourceCode(expandingRowsTemplate, Template.args) } },
    }}
    args={{
      template: expandingRowsTemplate,
      title: 'Table with expanding rows - NOTE: expandable property must be set to true',
      helperText: 'Click row to expand',
      useActions: false,
      useBatchActions: false,
      usePagination: true,
      expandable: true
    }}
    argTypes={{
      rowSize: { control: 'select', default: 'standard', options: ['compact', 'short', 'standard', 'tall'] },
      rowsSelected: { control: 'multi-select',  options: ['Java', 'COBOL', 'C++'] },
    }}
  >
    {Template.bind({})}
  </Story>
</Canvas>

# CvDataTableSkeleton

<Canvas>
  <Story
    name="Skeleton"
    parameters={{
      controls: { include: [ 'skeletonCols', 'skeletonRows', 'title', 'helperText', 'useBatchActions', 'useActions'] },
      docs: { source: { code: storySourceCode(skeletonTemplate, Template.args) } },
    }}
    args={{
      template: skeletonTemplate,
      title: 'Table title',
      helperText: 'Data has been requested...',
      skeletonRows: 5,
      skeletonCols: 5,
      useBatchActions: false,
      useActions: false,
      usePagination: true
    }}
    argTypes={{
    }}
  >
    {Template.bind({})}
  </Story>
</Canvas>


# Using v-model selected rows
If you are using the selected rows for batch actions or any other purpose, you should assign usable values to the rows.
  It is these values that are included in the selected rows events and in the selected rows v-model. Set the v-model on the
  cv-table like `<cv-table v-model:rows-selected="selectedRows" ...`

<Canvas>
  <Story
    name="v-model Selected Rows"
    parameters={{
      controls: { include: [ ] },
      docs: { source: { code: storySourceCode(vModelTemplate, Template.args) } },
    }}
    args={{
      template: vModelTemplate,
      title: 'v-model example',
      helperText: 'select rows to see updates',
      useBatchActions: true,
      useActions: false,
      usePagination: false
    }}
    argTypes={{
    }}
  >
    {Template.bind({})}
  </Story>
</Canvas>
