<template>
  <div>
    <v-data-table
      :caption="caption"
      :headers="headers"
      :items="records"
      v-model="selected"
      :options.sync="dataTablePagingOptions"
      :server-items-length="totalRecords"
      :loading="loading"
      :disable-sort="true"
      :show-select="showSelect"
      :single-select="singleSelect"
      :footer-props="{
        showCurrentPage: true,
        showFirstLastPage: true,
        itemsPerPageOptions: rowsPerPageItems,
        itemsPerPageText: lt('RowsPerPage'),
        pageText: lt('PageOfPageText')
      }"
      :loading-text="lt('Loading')"
      :no-data-text="lt('NoData')"
      class="elevation-1"
    >
      <!-- /*From server: UiDataTypes
 NoType = 0,v-on:item-selected="handleSelect"
        DateTime = 1,
        Date = 2,
        Time = 3,
        Text = 4,
        Integer = 5,
        Bool = 6,
        Decimal = 7,
        Currency = 8,
        Tags = 9,
        Enum = 10,
        EmailAddress = 11,
        HTTP = 12
*/ -->
      <template v-slot:body="{ items }">
        <tbody>
          <tr v-for="item in items" :key="item.id">
            <template v-if="showSelect">
              <td>
                <v-checkbox
                  v-model="selected"
                  :value="item"
                  primary
                  hide-details
                ></v-checkbox>
              </td>
            </template>
            <td v-for="c in item.columns" :key="c.key">
              <!-- Handle all plain text types right up to and including enums -->
              <!--TODO when get to coloured stuff will need to add that as a prop to column data but leaving out for now-->
              <template v-if="c.t < 11">
                <template v-if="c.i">
                  <!-- openable object with an ID -->
                  <v-btn depressed small @click="btnClick(c.key, c.i)">{{
                    c.v
                  }}</v-btn>
                </template>
                <template v-else>
                  {{ c.v }}
                </template>
              </template>
              <template v-if="c.t == 11">
                <a :href="'mailto:' + c.v">{{ c.v }}</a>
              </template>
              <template v-if="c.t == 12">
                <!-- Expects full url with protocol etc in c.v so might need to add to record builder -->
                <a :href="c.v" target="_blank">{{ c.v }}</a>
              </template>
            </td>
          </tr>
        </tbody>
      </template>
    </v-data-table>
    <hr />
    <div>Selected: {{ selected }}</div>
    <!--  <div>Headers: {{ headers }}</div>
    <div>Records: {{ records }}</div>
     <div>TotalRecords: {{ totalRecords }}</div>
     <div>caption: {{ caption }}</div>
    <div>apiBaseUrl: {{ apiBaseUrl }}</div>
    <div>formKey: {{ formKey }}</div>
    <div>dataListKey: {{ dataListKey }}</div>
    <div>dataFilterId: {{ dataFilterId }}</div>
    <div>viewPort is XS: {{ mini }}</div> -->
  </div>
</template>

<script>
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*  Xeslint-disable    */
////////////////////////////////////////////////////////////////////////////////////////////////////////////
export default {
  data() {
    return {
      loading: true,
      dataTablePagingOptions: {},
      headers: [],
      serverColumns: [],
      totalRecords: 0,
      records: [],
      rowsPerPageItems: [5, 10, 25, 50, 100],
      selected: []
    };
  },
  props: {
    apiBaseUrl: {
      type: String,
      default: "DataList/List"
    },
    formKey: String,
    dataListKey: String,
    caption: String,
    dataFilterId: {
      type: Number,
      default: 0
    },
    showSelect: {
      type: Boolean,
      default: false
    },
    singleSelect: {
      type: Boolean,
      default: false
    }
  },
  watch: {
    dataTablePagingOptions: {
      handler() {
        this.getDataFromApi();
      },
      deep: true
    },
    selected: function(newValue, oldValue) {
      if (newValue.length != oldValue.length) {
        this.handleSelectChange();
      }
    }
    // , //for now, not going with my own mini mode but may revisit so keeping this here but commented out for now
    // "$vuetify.breakpoint.xs": function(value) {
    //   this.getDataFromApi();
    // }
  },
  methods: {
    handleSelectChange() {
      //due to making own template for items need to handle singleselect which only affects if select all checkbox at top is visible when making own item template
      if (this.singleSelect) {
        this.selected.splice(0, this.selected.length - 1);
      }
      //emit event to parent form of selected rows
      //this.$emit("update:selected", this.selected);
      //Note that this bubbles up all the columns of all the selected rows
      //could be more efficient if it just sends the ID's instead:
      this.$emit("update:selected", window.$gz._.map(this.selected, "id"));
    },
    btnClick(key, i) {
      //translate key to actual object type from header data
      //key format is row-column e.g."500-2"
      //get the datatype of the column which matches the server columns array index
      var typeToOpen = this.serverColumns[key.split("-")[1]].ay;

      //i is the actual AyaNova index of that record so we have all we need to open that object
      window.$gz.eventBus.$emit("openobject", { type: typeToOpen, id: i });
    },
    lt(ltKey) {
      return window.$gz.locale.get(ltKey);
    },
    ltFormat() {
      return window.$gz.locale.format();
    },
    // mini() {
    //   //https://vuetifyjs.com/en/customization/breakpoints#breakpoint-service-object
    //   return this.$vuetify.breakpoint.xs;
    // },
    getDataFromApi() {
      //debugger;
      var that = this;

    
      //DataList/list?DataListKey=TestWidgetDataList&Offset=0&Limit=999&DataFilterId=1&mini=true

      //start with defaults
      var listOptions = {
        DataListKey: that.dataListKey,
        Limit: 100,
        Offset: 0
      };
      //calculate paging based on settings
      const { page, itemsPerPage } = that.dataTablePagingOptions;
      if (itemsPerPage && itemsPerPage > 0) {
        listOptions.Offset = (page - 1) * itemsPerPage;
        listOptions.Limit = itemsPerPage;
      }

      //is there a filter?
      if (that.dataFilterId != 0) {
        listOptions["DataFilterID"] = that.dataFilterId;
      }
      //Mini?
      //OK, seems as though the datatable has a built in ability to handle small viewports by displaying each record vertically instead so maybe I only need
      //mini for picklists
      // if (that.$vuetify.breakpoint.xs) {
      //   listOptions["Mini"] = true;
      // }

      that.loading = true;
      var listUrl =
        that.apiBaseUrl + "?" + window.$gz.api.buildQuery(listOptions);
      window.$gz.api.get(listUrl).then(res => {
        //NOTE: This is how to call an async function and await it from sync code
        (async function() {
          //Save a copy of the server columns data for handling button clicks etc later
          that.serverColumns = res.columns;
          //Make sure the locale keys are fetched
          await fetchLocalizedHeaderNames(res.columns); //Note can use await here because it's wrapped inside an async function call, it will wait then resume next stuff below
          //build that.headers here
          that.headers = buildHeaders(res.columns);
          //Post process data here and then set that.records
          that.records = buildRecords(
            res.data,
            res.columns,
            that.$options.filters //this is the VUE filters collection, nothing to do with the local data structure
          );
          that.loading = false;
          that.totalRecords = res.paging.count;

  //set the list settings in the store since we were successful at retrieval
      if (
        that.localFormSettings &&
        that.localFormSettings.pagination &&
        that.localFormSettings.pagination.itemsPerPage
      ) {
        window.$gz.form.setFormSettings(that.formKey, {
          temp: { page: that.localFormSettings.pagination.page },
          saved: {
            itemsPerPage: that.localFormSettings.pagination.itemsPerPage,
            sortBy: that.localFormSettings.pagination.sortBy,
            descending: that.localFormSettings.pagination.descending
          }
        });
      }


        })();
      });
    }
  }
};

//Called by getDataFromApi on retrieval of list with columnData
function buildHeaders(columnData) {
  //debugger;
  //iterate columns, build headers and return
  if (!columnData) {
    return [];
  }
  var ret = [];
  //iterate the columns, skip over the first one as it's the df column and not for display
  for (var i = 1; i < columnData.length; i++) {
    var cm = columnData[i];
    var h = {};
    h.text = window.$gz.locale.get(cm.cm);
    h.value = "columns.c" + i.toString(); //+".v";
    ret.push(h);
  }
  /*
{https://vuetifyjs.com/en/components/data-tables#api  see headers property for this info:
  text: string
  value: string
  align?: 'start' | 'center' | 'end'
  sortable?: boolean
  filterable?: boolean
  divider?: boolean
  class?: string | string[]
  width?: string | number
  filter?: (value: any, search: string, item: any) => boolean
  sort?: (a: any, b: any) => number
}

*/
  return ret;
}

//Called by getDataFromApi on retrieval of list with columnData
function buildRecords(listData, columndefinitions, filters) {
  //iterate data, build each object keyed with index name and display set to correct locale filter and then return
  if (!listData) {
    return;
  }
  var ret = [];

  //comes as an array of arrays, needs to leave as an array of objects representing each row
  for (var iRow = 0; iRow < listData.length; iRow++) {
    var row = listData[iRow];
    //iterate row and build object representing row data keyed to index
    //first column is the default column which sets the id for the row
    var o = { id: row[0].v, columns: {} };
    for (var iColumn = 1; iColumn < row.length; iColumn++) {
      var column = row[iColumn];

      var dataType = columndefinitions[iColumn].dt;
      var display = column.v;
      switch (dataType) {
        case 1: //datetime format to shortdatetime
          display = filters.shortdatelocalized(display);
          break;
        case 2: //date only
          display = filters.shortdateonlylocalized(display);
          break;
        case 3: //time only
          display = filters.shorttimeonlylocalized(display);
          break;
        case 6: //bool
          display = filters.boolastext(display);
          break;
        case 7: //decimal
          display = filters.decimal(display);
          break;
        case 8: //currency
          display = filters.currency(display);
          break;
        case 10: //enum
          display = filters.enum(display, columndefinitions[iColumn].et);
          break;
        default:
        //do nothing, allow it to stay as is
      }
      //build the row column object that will be used by the datatable
      var columnObject = {
        v: display,
        t: dataType,
        key: iRow + "-" + iColumn
      };
      //is the source dtalist field openable?  If so it will have an i property set for it's ID and we already know the types to open from the column headers data
      //so between the two we can make a clickable button in the grid that triggers a function with the column index and the id and that in turn will bubble up the event to open that
      //object
      if (column.i) {
        columnObject["i"] = column.i;
      }
      o.columns["c" + iColumn.toString()] = columnObject;
      //Is:
      //Headers: [ { "text": "Name", "value": "c1" }, { "text": "Serial #", "value": "c2" },
      //Records: [ { "id": 1, "c1": "Incredible Metal Fish 76", "c2": 1, "c3": "$877.8", "c4": "AuthorizationRoles.65536", "c5": "2020-01-30 01:53:57 AM", "c6": "Yup", "c7": "Virgil Strosin 74" }, { "id": 2, "c1": "Practical Plastic Bike 77", "c2": 2, "
      //CHANGE TO:
      //Headers: [ { "text": "Name", "value": "c1.v" }, { "text": "Serial #", "value": "c2" },
      //Records: [ { "id": 1,columns: {"c1": {v:"Incredible Metal Fish 76",t:THETYPE,key:ROWID-COLUMNID e.g. 1-1,1-2,2-1 etc}, "c2": 1, "c3": "$877.8", "c4": "AuthorizationRoles.65536", "c5": "2020-01-30 01:53:57 AM", "c6": "Yup", "c7": "Virgil Strosin 74" }, { "id": 2, "c1": "Practical Plastic Bike 77", "c2": 2, "
      //THis way can have v-if for each column that changes based on type and then has it's shit figured out
    }
    ret.push(o);
  }
  return ret;
}

/*UiDataTypes
 NoType = 0,
        DateTime = 1,
        Date = 2,
        Time = 3,
        Text = 4,
        Integer = 5,
        Bool = 6,
        Decimal = 7,
        Currency = 8,
        Tags = 9,
        Enum = 10,
        EmailAddress = 11
*/
//////////////////////////////////////////////////////////
//
// Ensures column names are present in locale table
//
async function fetchLocalizedHeaderNames(columnData) {
  if (!columnData) {
    return;
  }
  var headerKeys = [];
  for (var i = 1; i < columnData.length; i++) {
    var cm = columnData[i];
    headerKeys.push(cm.cm);
  }
  //Now fetch all the keys and await the response before returning
  await window.$gz.locale
    .fetch(headerKeys)
    .then(() => {
      return;
    })
    .catch(err => {
      that.formState.ready = true; //show the form anyway so we know what's what
      window.$gz.errorHandler.handleFormError(err);
    });
}

//DataTable component
//https://vuetifyjs.com/en/components/data-tables#paginate-and-sort-server-side
/*
TODO:
This handles fetching and displaying the data, the parent form handles all other aspects:
    - error message display
    - opening items
    - selecting filters and adding editing templates
    
 What is required to be sent to server:
    - example full request: DataList/list?DataListKey=TestWidgetDataList&Offset=0&Limit=999&DataFilterId=1
    - example mini request: DataList/list?DataListKey=TestWidgetDataList&Offset=0&Limit=999&DataFilterId=1&mini=true   
    - Offset        
    - Limit
    - DatafilterId
    - mini=true if XS otherwise nothing
        


What it needs from it's parent form:
    - form key for saving / getting persistent grid settings
    - api list url (maybe, or if all from datalist then no)
    - DataListKey value
    - filter id
    - refresh command
    - rows per page

What it needs to provide TO it's parent form
  - Custom event for this: https://vuejs.org/v2/guide/components-custom-events.html#sync-Modifier
    - Item click info to trigger opening edit form
    - Selected items list for mass ops
    - error event and message in case of server error or other error so parent can handle it 
        - Grid is responsible ONLY for showing data, nothing else
    

What will be delivered by the server:
Example request: http://localhost:7575/api/v8/DataList/List?Offset=2&Limit=2&DataListKey=TestWidgetDataList
Full response object:
{
  "data": [
    [
      {
        "v": 3
      },
      {
        "v": "Handcrafted Fresh Keyboard 27",
        "i": 3
      },
      {
        "v": 3
      },
      {
        "v": 697.34
      },
      {
        "v": 128
      },
      {
        "v": "2020-01-28T12:10:46.212435Z"
      },
      {
        "v": true
      },
      {
        "v": "Doug Effertz 17 - OpsAdminFull",
        "i": 18
      }
    ],
    [
      {
        "v": 4
      },
      {
        "v": "Unbranded Fresh Shoes 28",
        "i": 4
      },
      {
        "v": 4
      },
      {
        "v": 219.09
      },
      {
        "v": 16
      },
      {
        "v": "2020-01-28T12:33:14.347243Z"
      },
      {
        "v": true
      },
      {
        "v": "Samuel Powlowski 14 - CustomerLimited",
        "i": 15
      }
    ]
  ],
  "paging": {
    "count": 100,
    "offset": 2,
    "limit": 2,
    "first": "http://localhost:7575/api/v8/DataList/List?DataListKey=TestWidgetDataList&pageNo=1&pageSize=2",
    "previous": "http://localhost:7575/api/v8/DataList/List?DataListKey=TestWidgetDataList&pageNo=1&pageSize=2",
    "next": "http://localhost:7575/api/v8/DataList/List?DataListKey=TestWidgetDataList&pageNo=3&pageSize=2",
    "last": "http://localhost:7575/api/v8/DataList/List?DataListKey=TestWidgetDataList&pageNo=50&pageSize=2"
  },
  "columns": [
    {
      "cm": "df",
      "dt": 0,
      "ay": 2
    },
    {
      "cm": "WidgetName",
      "dt": 4,
      "ay": 2
    },
    {
      "cm": "WidgetSerial",
      "dt": 5
    },
    {
      "cm": "WidgetDollarAmount",
      "dt": 8
    },
    {
      "cm": "WidgetRoles",
      "dt": 10
    },
    {
      "cm": "WidgetStartDate",
      "dt": 1
    },
    {
      "cm": "Active",
      "dt": 6
    },
    {
      "cm": "User",
      "dt": 4,
      "ay": 3
    }
  ]
}

MINI Response object:
{
  "data": [
    [
      {
        "v": 3
      },
      {
        "v": "Handmade Soft Towels 27",
        "i": 3
      },
      {
        "v": 3
      }
    ],
    [
      {
        "v": 4
      },
      {
        "v": "Handcrafted Cotton Cheese 28",
        "i": 4
      },
      {
        "v": 4
      }
    ]
  ],
  "paging": {
    "count": 100,
    "offset": 2,
    "limit": 2,
    "first": "http://localhost:7575/api/v8/DataList/List?DataListKey=TestWidgetDataList&Mini=True&pageNo=1&pageSize=2",
    "previous": "http://localhost:7575/api/v8/DataList/List?DataListKey=TestWidgetDataList&Mini=True&pageNo=1&pageSize=2",
    "next": "http://localhost:7575/api/v8/DataList/List?DataListKey=TestWidgetDataList&Mini=True&pageNo=3&pageSize=2",
    "last": "http://localhost:7575/api/v8/DataList/List?DataListKey=TestWidgetDataList&Mini=True&pageNo=50&pageSize=2"
  },
  "columns": [
    {
      "cm": "df",
      "dt": 0,
      "ay": 2
    },
    {
      "cm": "Widget",
      "dt": 4,
      "ay": 2
    }
  ]
}

What this grid needs to do:
    - On created or refresh or change of filter
        - set Loading property to true on data object
        - send the get request to the server based on filter, viewport etc
            - On receipt of successful response
                - update the paging values
                - update the persistent form settings with the current grid selections for paging etc
                - generate the column headers 
                    - They will have locale keys so this grid fetches the keys as necessary at this point as it could change dynamically almost
                - Generate the Item slot template (which I've never done in code before but only in the template itself so needs research)
                    - set the property names in the incoming data to the correct matching headers
                    - set display filters based on locale settings (i.e. currency, datetime filter which converts to local time offset etc)              
                - fill the rows
                    - format?
            - On fail
                - Do something
        - set loading property to false



TODO:
     - Start coding grid here with vue component parameters and handlers first and in conjunction with test-widgets.vue
     - Once it's parent / component properties are set then get into the details




Headers: [ 
  { 
    "text": "Name", 
"value": "c1" }, { 
  "text": "Serial #", 
  "value": "c2" }, { "text": "Price", "value": "c3" }, { "text": "Roles", "value": "c4" }, { "text": "Start", "value": "c5" }, { "text": "Active", "value": "c6" }, { "text": "User", "value": "c7" } ]
Records: [ { "c1": "Awesome Steel Table 25", "c2": 1, "c3": 676.64, "c4": 0, "c5": "2020-01-28T16:50:29.371098Z", "c6": true, "c7": "Cameron Marvin 1 - BizAdminLimited" }, { "c1": "Fantastic Concrete Soap 26", "c2": 2, "c3": 310.6, "c4": 32768, "c5": "2020-01-28T15:56:47.362545Z", "c6": true, "c7": "Becky Parker 9 - TechFull" }, { "c1": "Handmade Soft Towels 27", "c2": 3, "c3": 463.7, "c4": 8, "c5": "2020-01-28T16:55:51.487005Z", "c6": true, "c7": "Zachary Renner 14 - CustomerLimited" }, { "c1": "Handcrafted Cotton Cheese 28", "c2": 4, "c3": 934.95, "c4": 1, "c5": "2020-01-28T16:55:23.324561Z", "c6": true, "c7": "Zachary Renner 14 - CustomerLimited" }, { "c1": "Refined Concrete Salad 29", "c2": 5, "c3": 758.3, "c4": 32, "c5": "2020-01-28T16:00:46.703856Z", "c6": true, "c7": "Terri Paucek 2 - BizAdminFull" }, { "c1": "Licensed Concrete Chips 30", "c2": 6, "c3": 580.73, "c4": 2048, "c5": "2020-01-28T16:44:29.601375Z", "c6": true, "c7": "Virginia Friesen 17 - OpsAdminFull" }, { "c1": "Handmade Cotton Pants 31", "c2": 7, "c3": 880.37, "c4": 1024, "c5": "2020-01-28T16:43:44.380156Z", "c6": true, "c7": "Bernadette Denesik 12 - SubContractorLimited" }, { "c1": "Refined Cotton Sausages 32", "c2": 8, "c3": 615.32, "c4": 1, "c5": "2020-01-28T16:33:10.667606Z", "c6": true, "c7": "Alberta Gleichner 22 - fr" }, { "c1": "Tasty Soft Hat 33", "c2": 9, "c3": 273.68, "c4": 512, "c5": "2020-01-28T16:19:12.318658Z", "c6": true, "c7": "Sadie Stehr 15 - CustomerFull" }, { "c1": "Refined Frozen Bike 35", "c2": 11, "c3": 538.56, "c4": 32, "c5": "2020-01-28T16:46:25.906627Z", "c6": true, "c7": "Sadie Stehr 15 - CustomerFull" } ]

 headers: [
          {
            text: 'Dessert (100g serving)',
            align: 'left',
            sortable: false,
            value: 'name',
          },
          { text: 'c2', value: 'c2' },
          { text: 'c3 (g)', value: 'c3' },
          { text: 'c4 (g)', value: 'c4' },
          { text: 'c5 (g)', value: 'c5' },
          { text: 'Iron (%)', value: 'c6' },
        ],

        [
          {
            name: 'Frozen Yogurt',
            c2: 159,
            c3: 6.0,
            c4: 24,
            c5: 4.0,
            c6: '1%',
          },
          {
            name: 'Ice cream sandwich',
            c2: 237,
            c3: 9.0,
            c4: 37,
            c5: 4.3,
            c6: '1%',
          },
          {
            name: 'Eclair',
            c2: 262,
            c3: 16.0,
            c4: 23,
            c5: 6.0,
            c6: '7%',
          },
          {
            name: 'Cupcake',
            c2: 305,
            c3: 3.7,
            c4: 67,
            c5: 4.3,
            c6: '8%',
          },
          {
            name: 'Gingerbread',
            c2: 356,
            c3: 16.0,
            c4: 49,
            c5: 3.9,
            c6: '16%',
          },
          {
            name: 'Jelly bean',
            c2: 375,
            c3: 0.0,
            c4: 94,
            c5: 0.0,
            c6: '0%',
          },
          {
            name: 'Lollipop',
            c2: 392,
            c3: 0.2,
            c4: 98,
            c5: 0,
            c6: '2%',
          },
          {
            name: 'Honeycomb',
            c2: 408,
            c3: 3.2,
            c4: 87,
            c5: 6.5,
            c6: '45%',
          },
          {
            name: 'Donut',
            c2: 452,
            c3: 25.0,
            c4: 51,
            c5: 4.9,
            c6: '22%',
          },
          {
            name: 'KitKat',
            c2: 518,
            c3: 26.0,
            c4: 65,
            c5: 7,
            c6: '6%',
          },
        ]
      },
    },
  }

*/
</script>
