<template>
  <v-container>
    <!--   <div>
      READY: {{ formState.ready }}
      <br />
      LOADING: {{ formState.loading }}
      <br />
      DIRTY: {{ formState.dirty }}
      <br />
      VALID: {{ formState.valid }}
      <br />
      READONLY: {{ formState.readOnly }}
      <br />
    </div>
     -->

    <v-row v-if="this.formState.ready">
      <v-col>
        <v-form ref="form">
          <v-row>
            <v-col cols="12" mt-1 mb-2>
              <v-alert
                ref="errorbox"
                v-show="formState.errorBoxMessage"
                color="error"
                icon="fa-exclamation-circle "
                transition="scale-transition"
                class="multi-line"
                outlined
                >{{ formState.errorBoxMessage }}</v-alert
              >
            </v-col>
            <v-col cols="12">
              <v-row>
                <v-col cols="12" sm="6" lg="4" xl="3">
                  <v-text-field
                    v-model="obj.name"
                    :readonly="this.formState.readOnly"
                    clearable
                    @click:clear="onChange('name')"
                    :counter="255"
                    :label="lt('Name')"
                    :rules="[
                      form().max255(this, 'name'),
                      form().required(this, 'name')
                    ]"
                    :error-messages="form().serverErrors(this, 'name')"
                    ref="name"
                    @change="onChange('name')"
                  ></v-text-field>
                </v-col>
                <v-col cols="12" sm="6" lg="4" xl="3">
                  <v-checkbox
                    v-model="obj.public"
                    :readonly="this.formState.readOnly"
                    :label="lt('AnyUser')"
                    ref="public"
                    @change="onChange('public')"
                  ></v-checkbox>
                </v-col>
              </v-row>
            </v-col>
            <template v-for="(item, index) in obj.editView">
              <v-col :key="item.key" cols="12" sm="6" lg="4" xl="3" px-2>
                <v-card>
                  <v-card-title>
                    {{ item.title }}
                  </v-card-title>

                  <v-card-text>
                    <!-- INCLUDE CONTROL -->
                    <v-switch
                      v-model="item.include"
                      :label="lt('Include')"
                      :ref="item.key"
                      :disabled="
                        item.sort != null || item.filter.items.length > 0
                      "
                      @change="includeChanged(item)"
                    ></v-switch>
                    <!-- RE-ORDER CONTROL -->
                    <div class="d-flex justify-space-between">
                      <v-btn large icon @click="move('start', index)"
                        ><v-icon large>fa-step-backward</v-icon></v-btn
                      >
                      <v-btn large icon @click="move('left', index)"
                        ><v-icon large>fa-backward</v-icon></v-btn
                      >
                      <v-btn large icon @click="move('right', index)"
                        ><v-icon large>fa-forward</v-icon></v-btn
                      >
                      <v-btn large icon @click="move('end', index)"
                        ><v-icon large>fa-step-forward</v-icon></v-btn
                      >
                    </div>
                    <!-- SORT CONTROL -->
                    <template v-if="item.isSortable">
                      <div @click="toggleSort(item)" class="pt-6">
                        <v-btn x-large v-if="item.sort == null" icon>
                          <v-icon x-large>fa-sort</v-icon></v-btn
                        >
                        <v-btn
                          v-if="item.sort != null && item.sort == '-'"
                          icon
                          x-large
                          ><v-icon color="primary" x-large
                            >fa-sort-amount-down</v-icon
                          ></v-btn
                        >
                        <v-btn
                          v-if="item.sort != null && item.sort == '+'"
                          icon
                          x-large
                          ><v-icon color="primary" x-large
                            >fa-sort-amount-up</v-icon
                          ></v-btn
                        >
                        <label class="v-label theme--light"
                          >&nbsp;{{ lt("Sort") }}</label
                        >
                      </div>
                    </template>

                    <!-- FILTER CONTROL -->
                    <template v-if="item.isFilterable">
                      <div class="pt-6">
                        <!-- ******** BUILDER FOR EACH TYPE Tag, decimal,currency, bool, integer, string, datetime ******** -->
                        <!-- DATETIME BUILDER   @change="dateTokenChanged(item)"-->
                        <div v-if="item.uiFieldDataType === 1">
                          <v-select
                            v-model="item.tempFilterToken"
                            :items="pickLists.dateFilterTokens"
                            item-text="name"
                            item-value="id"
                            :label="lt('Filter')"
                            prepend-icon="fa-filter"
                          ></v-select>
                          <div v-if="item.tempFilterToken == '*select*'">
                            <v-select
                              v-model="item.tempFilterOperator"
                              :items="pickLists.dateFilterOperators"
                              item-text="name"
                              item-value="id"
                            ></v-select>
                            <gz-date-time-picker
                              v-if="
                                item.tempFilterOperator != '*NOVALUE*' &&
                                  item.tempFilterOperator != '*HASVALUE*'
                              "
                              v-model="item.tempFilterValue"
                            ></gz-date-time-picker>
                          </div>
                          <v-btn
                            large
                            block
                            v-if="item.tempFilterToken != null"
                            @click="addFilterCondition(item)"
                            ><v-icon large>fa-plus</v-icon></v-btn
                          >
                        </div>

                        <!-- STRING(text-4, emailaddress-11, http-12) BUILDER  -->
                        <div
                          v-if="
                            item.uiFieldDataType === 4 ||
                              item.uiFieldDataType === 11 ||
                              item.uiFieldDataType === 12
                          "
                        >
                          <v-select
                            v-model="item.tempFilterOperator"
                            :items="pickLists.stringFilterOperators"
                            item-text="name"
                            item-value="id"
                            :label="lt('Filter')"
                            prepend-icon="fa-filter"
                          ></v-select>
                          <v-text-field
                            v-if="
                              item.tempFilterOperator != null &&
                                item.tempFilterOperator != '*NOVALUE*' &&
                                item.tempFilterOperator != '*HASVALUE*'
                            "
                            v-model="item.tempFilterValue"
                            clearable
                          ></v-text-field>
                          <v-btn
                            large
                            block
                            v-if="item.tempFilterOperator != null"
                            @click="addFilterCondition(item)"
                            ><v-icon large>fa-plus</v-icon></v-btn
                          >
                        </div>

                        <!-- INTEGER BUILDER  -->
                        <div v-if="item.uiFieldDataType === 5">
                          <v-select
                            v-model="item.tempFilterOperator"
                            :items="pickLists.integerFilterOperators"
                            item-text="name"
                            item-value="id"
                            :label="lt('Filter')"
                            prepend-icon="fa-filter"
                          ></v-select>
                          <v-text-field
                            v-if="
                              item.tempFilterOperator != null &&
                                item.tempFilterOperator != '*NOVALUE*' &&
                                item.tempFilterOperator != '*HASVALUE*'
                            "
                            v-model="item.tempFilterValue"
                            clearable
                            type="number"
                          ></v-text-field>
                          <v-btn
                            large
                            block
                            v-if="item.tempFilterOperator != null"
                            @click="addFilterCondition(item)"
                            ><v-icon large>fa-plus</v-icon></v-btn
                          >
                        </div>
                        <!-- BOOL BUILDER  -->
                        <div v-if="item.uiFieldDataType === 6">
                          <v-select
                            v-model="item.tempFilterOperator"
                            :items="pickLists.boolFilterOperators"
                            item-text="name"
                            item-value="id"
                            :label="lt('Filter')"
                            prepend-icon="fa-filter"
                          ></v-select>
                          <v-radio-group
                            v-model="item.tempFilterValue"
                            v-if="
                              item.tempFilterOperator != null &&
                                item.tempFilterOperator != '*NOVALUE*' &&
                                item.tempFilterOperator != '*HASVALUE*'
                            "
                            row
                          >
                            <v-radio
                              :label="lt('False')"
                              :value="false"
                            ></v-radio>
                            <v-radio
                              :label="lt('True')"
                              :value="true"
                            ></v-radio>
                          </v-radio-group>

                          <v-btn
                            large
                            block
                            v-if="item.tempFilterOperator != null"
                            @click="addFilterCondition(item)"
                            ><v-icon large>fa-plus</v-icon></v-btn
                          >
                        </div>

                        <!-- DECIMAL BUILDER -->
                        <div v-if="item.uiFieldDataType === 7">
                          <v-select
                            v-model="item.tempFilterOperator"
                            :items="pickLists.decimalFilterOperators"
                            item-text="name"
                            item-value="id"
                            :label="lt('Filter')"
                            prepend-icon="fa-filter"
                          ></v-select>
                          <gz-decimal
                            v-if="
                              item.tempFilterOperator != null &&
                                item.tempFilterOperator != '*NOVALUE*' &&
                                item.tempFilterOperator != '*HASVALUE*'
                            "
                            v-model="item.tempFilterValue"
                            clearable
                          ></gz-decimal>
                          <v-btn
                            large
                            block
                            v-if="item.tempFilterOperator != null"
                            @click="addFilterCondition(item)"
                            ><v-icon large>fa-plus</v-icon></v-btn
                          >
                        </div>
                        <!-- CURRENCY BUILDER  -->
                        <div v-if="item.uiFieldDataType === 8">
                          <v-select
                            v-model="item.tempFilterOperator"
                            :items="pickLists.decimalFilterOperators"
                            item-text="name"
                            item-value="id"
                            :label="lt('Filter')"
                            prepend-icon="fa-filter"
                          ></v-select>
                          <gz-currency
                            v-if="
                              item.tempFilterOperator != null &&
                                item.tempFilterOperator != '*NOVALUE*' &&
                                item.tempFilterOperator != '*HASVALUE*'
                            "
                            v-model="item.tempFilterValue"
                            clearable
                          ></gz-currency>
                          <v-btn
                            large
                            block
                            v-if="item.tempFilterOperator != null"
                            @click="addFilterCondition(item)"
                            ><v-icon large>fa-plus</v-icon></v-btn
                          >
                        </div>
                        <!-- TAG BUILDER  -->
                        <div v-if="item.uiFieldDataType === 9">
                          <v-select
                            v-model="item.tempFilterOperator"
                            :items="pickLists.tagFilterOperators"
                            item-text="name"
                            item-value="id"
                            :label="lt('Filter')"
                            prepend-icon="fa-filter"
                          ></v-select>

                          <gz-tag-picker
                            v-if="item.tempFilterOperator != null"
                            v-model="item.tempFilterValue"
                          ></gz-tag-picker>

                          <v-btn
                            large
                            block
                            v-if="item.tempFilterOperator != null"
                            @click="addFilterCondition(item)"
                            ><v-icon large>fa-plus</v-icon></v-btn
                          >
                        </div>
                        <!-- ENUM BUILDER  -->
                        <div v-if="item.uiFieldDataType === 10">
                          <v-select
                            v-model="item.tempFilterOperator"
                            :items="pickLists.enumFilterOperators"
                            item-text="name"
                            item-value="id"
                            :label="lt('Filter')"
                            prepend-icon="fa-filter"
                          ></v-select>

                          <v-select
                            v-if="
                              item.tempFilterOperator != null &&
                                item.tempFilterOperator != '*NOVALUE*' &&
                                item.tempFilterOperator != '*HASVALUE*'
                            "
                            v-model="item.tempFilterValue"
                            :items="enumPickList(item.enumType)"
                            item-text="name"
                            item-value="id"
                          ></v-select>

                          <v-btn
                            large
                            block
                            v-if="item.tempFilterOperator != null"
                            @click="addFilterCondition(item)"
                            ><v-icon large>fa-plus</v-icon></v-btn
                          >
                        </div>
                      </div>

                      <div class="pt-6">
                        <!-- FILTER LIST -->
                        <template v-if="item.filter.items.length > 0">
                          <v-list elevation="2">
                            <v-subheader v-if="item.filter.items.length > 1">
                              <!-- AND / OR FILTER CONDITIONS -->
                              <v-radio-group v-model="item.filter.any" row>
                                <v-radio
                                  :label="lt('GridFilterDialogAndRadioText')"
                                  :value="false"
                                ></v-radio>
                                <v-radio
                                  :label="lt('GridFilterDialogOrRadioText')"
                                  :value="true"
                                ></v-radio> </v-radio-group
                            ></v-subheader>
                            <v-list-item
                              v-for="(filterItem, index) in item.filter.items"
                              :key="index"
                            >
                              <v-list-item-content>
                                <v-list-item-title v-text="filterItem.display">
                                </v-list-item-title>
                              </v-list-item-content>
                              <v-list-item-action>
                                <v-btn
                                  icon
                                  @click="removeFilterCondition(item, index)"
                                >
                                  <v-icon>fa-trash-alt</v-icon>
                                </v-btn>
                              </v-list-item-action>
                            </v-list-item>
                          </v-list>
                        </template>
                        <!-- <v-divider></v-divider>
                        {{ item }} -->
                      </div>
                    </template>
                  </v-card-text>
                </v-card>
              </v-col>
            </template>
          </v-row>
        </v-form>
      </v-col>
    </v-row>
  </v-container>
</template>
<script>
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*  Xeslint-disable    */
////////////////////////////////////////////////////////////////////////////////////////////////////////////

const FORM_KEY = "ay-data-list-view";
const API_BASE_URL = "DataListView/";
export default {
  // beforeRouteEnter(to, from, next) {
  //   var ltKeysRequired = ["DataListView", "GridFilterName"];

  //   window.$gz.locale.fetch(ltKeysRequired).then(next);
  // },
  //unsaved changes are actually valid for this form so no need to warn
  beforeRouteLeave(to, from, next) {
    var vm = this;
    if (this.formState.dirty) {
      //Put in unsaved listview
      debugger;
      var formSettings = window.$gz.form.getFormSettings(vm.formKey);
      formSettings.saved.dataTable.unsavedListView = JSON.stringify(
        generateListViewFromEdited(vm)
      );
      formSettings.saved.dataTable.listViewId = -1;
      window.$gz.form.setFormSettings(vm.formKey, formSettings);
      next();
    } else {
      next();
    }
  },
  beforeDestroy() {
    window.$gz.eventBus.$off("menu-click", clickHandler);
  },
  created() {
    var vm = this;

    //set route values in data object so init form can handle
    vm.dataListKey = this.$route.params.dataListKey;
    vm.listViewId = this.$route.params.listViewId;
    vm.formKey = this.$route.params.formKey;
    //console.log("Created TOP calling initform...");
    initForm(vm)
      .then(() => {
        //console.log("CREATED: back from initform");
        //  path: "/ay-data-list-view/:listViewId/:dataListKey",
        vm.formState.ready = true;

        window.$gz.eventBus.$on("menu-click", clickHandler);
        //NOTE: this would normally be in getDataFromAPI but this form doesn't really need that function so doing it here
        //modify the menu as necessary
        generateMenu(vm, false); //default is never read only and passing in this vm
        //init disable save button so it can be enabled only on edit to show dirty form
        window.$gz.eventBus.$emit("menu-disable-item", FORM_KEY + ":save");
        vm.formState.loading = false;
      })
      .catch(err => {
        //console.log("CREATED: ERROR back from initform with error");
        vm.formState.ready = true;
        window.$gz.errorHandler.handleFormError(err);
      });
  },
  data() {
    return {
      obj: { editView: [], name: "", public: true },
      listViewId: undefined,
      dataListKey: undefined,
      formKey: undefined,
      fieldDefinitions: [],
      effectiveListView: undefined,
      concurrencyToken: undefined,
      pickLists: {
        dateFilterOperators: [],
        dateFilterTokens: [],
        stringFilterOperators: [],
        integerFilterOperators: [],
        boolFilterOperators: [],
        decimalFilterOperators: [],
        tagFilterOperators: [],
        enumFilterOperators: []
      },
      formState: {
        ready: false,
        dirty: false,
        valid: true,
        readOnly: false,
        loading: true,
        errorBoxMessage: undefined,
        appError: undefined,
        serverError: {}
      },
      rights: window.$gz.role.getRights(window.$gz.type.DataListView)
    };
  },
  //WATCHERS
  watch: {
    formState: {
      handler: function(val) {
        //,oldval is available here too if necessary
        if (this.formState.loading) {
          return;
        }

        //enable / disable save button
        var canSave = val.dirty && val.valid && !val.readOnly;
        if (canSave) {
          window.$gz.eventBus.$emit("menu-enable-item", FORM_KEY + ":save");
        } else {
          window.$gz.eventBus.$emit("menu-disable-item", FORM_KEY + ":save");
        }

        //enable / disable duplicate button
        var canDuplicate = !val.dirty && val.valid && !val.readOnly;
        if (canDuplicate) {
          window.$gz.eventBus.$emit(
            "menu-enable-item",
            FORM_KEY + ":duplicate"
          );
        } else {
          window.$gz.eventBus.$emit(
            "menu-disable-item",
            FORM_KEY + ":duplicate"
          );
        }
      },
      deep: true
    }
  },
  computed: {
    canSave: function() {
      return this.formState.valid && this.formState.dirty;
    },
    canDuplicate: function() {
      return this.formState.valid && !this.formState.dirty;
    }
  },
  methods: {
    lt: function(ltkey) {
      return window.$gz.locale.get(ltkey);
    },
    enumPickList: function(enumKey) {
      return window.$gz.enums.getPickList(enumKey);
    },
    includeChanged: function(item) {
      if (item.required && item.visible == false) {
        item.required = false;
      }
      window.$gz.form.setFormState({
        vm: this,
        dirty: true
      });
    },
    toggleSort: function(item) {
      if (item.sort == null) {
        item.sort = "+";
      } else if (item.sort == "+") {
        item.sort = "-";
      } else {
        item.sort = null;
      }
      //make sure sorted fields are INCLUDED
      if (item.sort) {
        item.include = true;
      }
      window.$gz.form.setFormState({
        vm: this,
        dirty: true
      });
    },
    move: function(direction, index) {
      var totalItems = this.obj.editView.length;
      var newIndex = 0;
      //calculate new index
      switch (direction) {
        case "start":
          newIndex = 0;
          break;
        case "left":
          newIndex = index - 1;
          if (newIndex < 0) {
            newIndex = 0;
          }
          break;
        case "right":
          newIndex = index + 1;
          if (newIndex > totalItems - 1) {
            newIndex = totalItems - 1;
          }

          break;
        case "end":
          newIndex = totalItems - 1;
          break;
      }

      this.obj.editView.splice(
        newIndex,
        0,
        this.obj.editView.splice(index, 1)[0]
      );
      window.$gz.form.setFormState({
        vm: this,
        dirty: true
      });
    },
    addFilterCondition(item) {
      var filterItem = { op: null, value: null, display: null };
      var filterItemSet = false;
      //DATE relative token?
      if (item.uiFieldDataType === 1) {
        //some kind of relative date token?
        if (item.tempFilterToken && item.tempFilterToken != "*select*") {
          //special relative token
          filterItem.op = "="; //equality
          filterItem.value = item.tempFilterToken;
          filterItemSet = true;
        }
      }

      //BLANKS / NONBLANKS TOKENS?
      if (false == filterItemSet && item.tempFilterOperator == "*NOVALUE*") {
        filterItem.op = "=";
        filterItem.value = "*NULL*";
        filterItemSet = true;
      }

      if (false == filterItemSet && item.tempFilterOperator == "*HASVALUE*") {
        filterItem.op = "!=";
        filterItem.value = "*NULL*";
        filterItemSet = true;
      }

      //JUST REGULAR FILTER ITEM
      if (
        false == filterItemSet &&
        item.tempFilterOperator &&
        item.tempFilterValue != null
      ) {
        filterItem.op = item.tempFilterOperator;
        filterItem.value = item.tempFilterValue;
        //only add if there is both an op and a value
        //above here for tokens that isn't a restriction but
        //after passing through those conditions were at a point where there MUST be both
        if (filterItem.op && filterItem.value != null) {
          filterItemSet = true;
        }
      }

      if (filterItemSet) {
        //display
        filterItem.display = getDisplayForFilter(
          this,
          item.uiFieldDataType,
          filterItem.op,
          filterItem.value,
          item.enumType
        );
        //add only if not already in the collection (accidental double click)
        if (!window.$gz._.find(item.filter.items, filterItem)) {
          item.filter.items.push(filterItem);
          window.$gz.form.setFormState({
            vm: this,
            dirty: true
          });
        }
        return;
      }
    },
    removeFilterCondition(item, index) {
      item.filter.items.splice(index, 1);
      window.$gz.form.setFormState({
        vm: this,
        dirty: true
      });
    },
    form() {
      return window.$gz.form;
    },
    onChange(ref) {
      if (!this.formState.loading && !this.formState.readOnly) {
        window.$gz.form.onChange(this, ref);
      }
    },
    submit() {
      //   var vm = this;
      //   var url = API_BASE_URL + this.formCustomTemplateKey;
      //   //clear any errors vm might be around from previous submit
      //   window.$gz.form.deleteAllErrorBoxErrors(this);
      //   //Create template data object here....
      //   //Note that server expects to see a string array of json template, not actual json
      //   var newObj = {
      //     formKey: this.formCustomTemplateKey,
      //     concurrencyToken: this.concurrencyToken,
      //     template: "[]"
      //   };
      //   //temporary array to hold template for later stringification
      //   var temp = [];
      //   //Rules:
      //   for (var i = 0; i < this.obj.length; i++) {
      //     var fldItem = this.obj[i];
      //     if (fldItem.custom == false) {
      //       //Process regular stock field
      //       //If it's *not* set to stockRequired (i.e. built in field with biz rules that can't be hidden or changed)
      //       // and it's also set to hidden or required then it's template-worthy
      //       if (
      //         !fldItem.stockRequired &&
      //         (fldItem.visible == false || fldItem.required == true)
      //       ) {
      //         temp.push({
      //           fld: fldItem.key,
      //           required: fldItem.required,
      //           hide: !fldItem.visible
      //         });
      //       }
      //     } else {
      //       //Process custom field
      //       //If it's not visible then don't add it at all
      //       if (fldItem.visible == true) {
      //         temp.push({
      //           fld: fldItem.key,
      //           required: fldItem.required,
      //           type: fldItem.type
      //         });
      //       }
      //     }
      //   }
      //   //now set the template as a json string
      //   newObj.template = JSON.stringify(temp);
      //   window.$gz.api
      //     .upsert(url, newObj)
      //     .then(res => {
      //       vm.formState.loading = false;
      //       if (res.error != undefined) {
      //         vm.formState.serverError = res.error;
      //         window.$gz.form.setErrorBoxErrors(vm);
      //       } else {
      //         //Handle "put" of an existing record (UPDATE) (there is no POST of a new record for this particular object)
      //         //Set store values for template and token
      //         window.$gz.formCustomTemplate.set(
      //           vm.formCustomTemplateKey,
      //           res.data.concurrencyToken,
      //           newObj.template
      //         );
      //         //set our local concurrency token value
      //         vm.concurrencyToken = res.data.concurrencyToken;
      //         //form is now clean
      //         window.$gz.form.setFormState({
      //           vm: vm,
      //           dirty: false
      //         });
      //       }
      //     })
      //     .catch(function handleSubmitError(error) {
      //       vm.formState.loading = false;
      //       window.$gz.errorHandler.handleFormError(error, vm);
      //     });
    }
  }
};

/////////////////////////////
//
//
function clickHandler(menuItem) {
  if (!menuItem) {
    return;
  }
  var m = window.$gz.menu.parseMenuItem(menuItem);
  if (m.owner == FORM_KEY && !m.disabled) {
    switch (m.key) {
      case "save":
        m.vm.submit();
        break;
      case "delete":
        m.vm.remove();
        break;
      case "duplicate":
        m.vm.duplicate();
        break;
      default:
        window.$gz.eventBus.$emit(
          "notify-warning",
          FORM_KEY + "::context click: [" + m.key + "]"
        );
    }
  }
}

//////////////////////
//
//
function generateMenu(vm) {
  var menuOptions = {
    isMain: false,
    icon: "filter",
    title: window.$gz.locale.get("DataListView"),
    helpUrl: "form-ay-data-list-view",
    formData: {
      formKey: FORM_KEY,
      ayaType: window.$gz.type.FormCustom,
      formCustomTemplateKey: undefined
    },
    menuItems: []
  };

  if (vm.rights.change) {
    menuOptions.menuItems.push({
      title: window.$gz.locale.get("Save"),
      icon: "save",
      surface: true,
      key: FORM_KEY + ":save",
      vm: vm
    });
  }
  if (vm.rights.delete) {
    menuOptions.menuItems.push({
      title: window.$gz.locale.get("Delete"),
      icon: "trash-alt",
      surface: true,
      key: FORM_KEY + ":delete",
      vm: vm
    });
  }
  if (vm.rights.change) {
    menuOptions.menuItems.push({
      title: window.$gz.locale.get("Duplicate"),
      icon: "clone",
      key: FORM_KEY + ":duplicate",
      vm: vm
    });
  }
  window.$gz.eventBus.$emit("menu-change", menuOptions);
}

/////////////////////////////////
//
//
function initForm(vm) {
  return new Promise(function(resolve, reject) {
    (async function() {
      try {
        await fetchUILocalizedText(vm);
        await populatePickLists(vm);
        await populateFieldDefinitions(vm);
        await fetchLocalizedFieldNames(vm);
        await setEffectiveListView(vm);
        await initDataObject(vm);
        await fetchEnums(vm);
      } catch (err) {
        reject(err);
      }
      resolve();
    })();
  });
}

//////////////////////////////////////////////////////////
//
// Ensures UI localized text is available
//
function fetchUILocalizedText(vm) {
  var ltKeysRequired = [
    "DataListView",
    "GridFilterName",
    "Include",
    "AnyUser",
    "Sort",
    "Filter",
    "GridFilterDialogAndRadioText",
    "GridFilterDialogOrRadioText",
    "GridRowFilterDropDownBlanksItem",
    "GridRowFilterDropDownNonBlanksItem",
    "GridRowFilterDropDownEquals",
    "GridRowFilterDropDownGreaterThan",
    "GridRowFilterDropDownGreaterThanOrEqualTo",
    "GridRowFilterDropDownLessThan",
    "GridRowFilterDropDownLessThanOrEqualTo",
    "GridRowFilterDropDownNotEquals",
    "GridRowFilterDropDownDoesNotContain",
    "GridRowFilterDropDownContains",
    "GridRowFilterDropDownStartsWith",
    "GridRowFilterDropDownEndsWith",
    "SelectItem",
    "DateRangeYesterday",
    "DateRangeToday",
    "DateRangeTomorrow",
    "DateRangeLastWeek",
    "DateRangeThisWeek",
    "DateRangeNextWeek",
    "DateRangeLastMonth",
    "DateRangeThisMonth",
    "DateRangeNextMonth",
    "DateRange14DayWindow",
    "DateRangePast",
    "DateRangeFuture",
    "DateRangeLastYear",
    "DateRangeThisYear",
    "DateRangeInTheLastThreeMonths",
    "DateRangeInTheLastSixMonths",
    "DateRangePastYear",
    "DateRangePast90Days",
    "DateRangePast30Days",
    "DateRangePast24Hours",
    "True",
    "False",
    "Name"
  ];

  return window.$gz.locale.fetch(ltKeysRequired);
}

/////////////////////////////////
//
//
function populatePickLists(vm) {
  vm.pickLists.dateFilterOperators.push(
    ...[
      { name: vm.lt("GridRowFilterDropDownBlanksItem"), id: "*NOVALUE*" },
      {
        name: vm.lt("GridRowFilterDropDownNonBlanksItem"),
        id: "*HASVALUE*"
      },
      { name: vm.lt("GridRowFilterDropDownEquals"), id: "=" },
      { name: vm.lt("GridRowFilterDropDownGreaterThan"), id: ">" },
      {
        name: vm.lt("GridRowFilterDropDownGreaterThanOrEqualTo"),
        id: ">="
      },
      { name: vm.lt("GridRowFilterDropDownLessThan"), id: "<" },
      { name: vm.lt("GridRowFilterDropDownLessThanOrEqualTo"), id: "<=" },
      { name: vm.lt("GridRowFilterDropDownNotEquals"), id: "!=" }
    ]
  );

  vm.pickLists.dateFilterTokens.push(
    ...[
      { name: "(" + vm.lt("SelectItem") + ")", id: "*select*" }, //If select then use entry in date /time picker
      { name: vm.lt("DateRangeYesterday"), id: "*yesterday*" },
      { name: vm.lt("DateRangeToday"), id: "*today*" },
      { name: vm.lt("DateRangeTomorrow"), id: "*tomorrow*" },
      { name: vm.lt("DateRangeLastWeek"), id: "*lastweek*" },
      { name: vm.lt("DateRangeThisWeek"), id: "*thisweek*" },
      { name: vm.lt("DateRangeNextWeek"), id: "*nextweek*" },
      { name: vm.lt("DateRangeLastMonth"), id: "*lastmonth*" },
      { name: vm.lt("DateRangeThisMonth"), id: "*thismonth*" },
      { name: vm.lt("DateRangeNextMonth"), id: "*nextmonth*" },
      { name: vm.lt("DateRange14DayWindow"), id: "*14daywindow*" },
      { name: vm.lt("DateRangePast"), id: "*past*" },
      { name: vm.lt("DateRangeFuture"), id: "*future*" },
      { name: vm.lt("DateRangeLastYear"), id: "*lastyear*" }, //prior year from jan to dec
      { name: vm.lt("DateRangeThisYear"), id: "*thisyear*" },
      {
        name: vm.lt("DateRangeInTheLastThreeMonths"),
        id: "*last3months*"
      },
      {
        name: vm.lt("DateRangeInTheLastSixMonths"),
        id: "*last6months*"
      },
      { name: vm.lt("DateRangePastYear"), id: "*pastyear*" }, //last 365 days

      { name: vm.lt("DateRangePast90Days"), id: "*past90days*" },
      { name: vm.lt("DateRangePast30Days"), id: "*past30days*" },
      { name: vm.lt("DateRangePast24Hours"), id: "*past24hours*" }
    ]
  );

  vm.pickLists.stringFilterOperators.push(
    ...[
      { name: vm.lt("GridRowFilterDropDownBlanksItem"), id: "*NOVALUE*" },
      {
        name: vm.lt("GridRowFilterDropDownNonBlanksItem"),
        id: "*HASVALUE*"
      },
      { name: vm.lt("GridRowFilterDropDownEquals"), id: "=" },
      { name: vm.lt("GridRowFilterDropDownGreaterThan"), id: ">" },
      {
        name: vm.lt("GridRowFilterDropDownGreaterThanOrEqualTo"),
        id: ">="
      },
      { name: vm.lt("GridRowFilterDropDownLessThan"), id: "<" },
      { name: vm.lt("GridRowFilterDropDownLessThanOrEqualTo"), id: "<=" },
      { name: vm.lt("GridRowFilterDropDownNotEquals"), id: "!=" },
      { name: vm.lt("GridRowFilterDropDownDoesNotContain"), id: "!-%-" },
      { name: vm.lt("GridRowFilterDropDownContains"), id: "-%-" },
      { name: vm.lt("GridRowFilterDropDownStartsWith"), id: "%-" },
      { name: vm.lt("GridRowFilterDropDownEndsWith"), id: "-%" }
    ]
  );

  vm.pickLists.integerFilterOperators.push(
    ...[
      { name: vm.lt("GridRowFilterDropDownBlanksItem"), id: "*NOVALUE*" },
      {
        name: vm.lt("GridRowFilterDropDownNonBlanksItem"),
        id: "*HASVALUE*"
      },
      { name: vm.lt("GridRowFilterDropDownEquals"), id: "=" },
      { name: vm.lt("GridRowFilterDropDownGreaterThan"), id: ">" },
      {
        name: vm.lt("GridRowFilterDropDownGreaterThanOrEqualTo"),
        id: ">="
      },
      { name: vm.lt("GridRowFilterDropDownLessThan"), id: "<" },
      { name: vm.lt("GridRowFilterDropDownLessThanOrEqualTo"), id: "<=" },
      { name: vm.lt("GridRowFilterDropDownNotEquals"), id: "!=" }
    ]
  );

  vm.pickLists.boolFilterOperators.push(
    ...[
      { name: vm.lt("GridRowFilterDropDownBlanksItem"), id: "*NOVALUE*" },
      {
        name: vm.lt("GridRowFilterDropDownNonBlanksItem"),
        id: "*HASVALUE*"
      },
      { name: vm.lt("GridRowFilterDropDownEquals"), id: "=" },
      { name: vm.lt("GridRowFilterDropDownNotEquals"), id: "!=" }
    ]
  );

  vm.pickLists.decimalFilterOperators.push(
    ...[
      { name: vm.lt("GridRowFilterDropDownBlanksItem"), id: "*NOVALUE*" },
      {
        name: vm.lt("GridRowFilterDropDownNonBlanksItem"),
        id: "*HASVALUE*"
      },
      { name: vm.lt("GridRowFilterDropDownEquals"), id: "=" },
      { name: vm.lt("GridRowFilterDropDownGreaterThan"), id: ">" },
      {
        name: vm.lt("GridRowFilterDropDownGreaterThanOrEqualTo"),
        id: ">="
      },
      { name: vm.lt("GridRowFilterDropDownLessThan"), id: "<" },
      { name: vm.lt("GridRowFilterDropDownLessThanOrEqualTo"), id: "<=" },
      { name: vm.lt("GridRowFilterDropDownNotEquals"), id: "!=" }
    ]
  );
  //tags filter only by equals in initial release, see DataListSqlFilterCriteriaBuilder.cs line 523 for deets
  vm.pickLists.tagFilterOperators.push({
    name: vm.lt("GridRowFilterDropDownEquals"),
    id: "="
  });

  vm.pickLists.enumFilterOperators.push(
    ...[
      { name: vm.lt("GridRowFilterDropDownBlanksItem"), id: "*NOVALUE*" },
      {
        name: vm.lt("GridRowFilterDropDownNonBlanksItem"),
        id: "*HASVALUE*"
      },
      { name: vm.lt("GridRowFilterDropDownEquals"), id: "=" },
      { name: vm.lt("GridRowFilterDropDownNotEquals"), id: "!=" }
    ]
  );
}

////////////////////
//
function populateFieldDefinitions(vm) {
  //http://localhost:7575/api/v8/DataList/ListFields?DataListKey=TestWidgetDataList
  return window.$gz.api
    .get("DataList/ListFields?DataListKey=" + vm.dataListKey)
    .then(res => {
      if (res.error != undefined) {
        throw res.error;
      } else {
        vm.fieldDefinitions = res.data;
      }
    });
}

//////////////////////////////////////////////////////////
//
// Ensures column names are present in locale table
//
function fetchLocalizedFieldNames(vm) {
  var columnKeys = [];
  for (var i = 1; i < vm.fieldDefinitions.length; i++) {
    var cm = vm.fieldDefinitions[i];
    columnKeys.push(cm.ltKey);
  }
  //Now fetch all the keys and await the response before returning
  return window.$gz.locale.fetch(columnKeys).then(() => {
    return;
  });
}

/////////////////////////////////
//
//
function setEffectiveListView(vm) {
  /*
  effectiveListView
  - Second get the ListView that is currently in use so can setup the page view
			- If listviewid is zero then that's starting with the default list view so need to fetch it and then init the form
			- If listviewid is -1 then that's starting with an unsaved listview so get that from the saved form store
			- If listviewid is greater than 0 then it's a saved listview and there sb a cached version of it but ideally maybe fetch it from 

  */

  if (vm.listViewId == null) {
    throw "ay-data-list::setEffectiveListView - listViewId is not set";
  }

  var formSettings = window.$gz.form.getFormSettings(vm.formKey);

  if (vm.listViewId == -1) {
    if (formSettings.saved.dataTable.unsavedListView != null) {
      vm.effectiveListView = JSON.parse(
        formSettings.saved.dataTable.unsavedListView
      );
      vm.obj.name = vm.lt("FilterUnsaved");
      return Promise.resolve();
    }
  } else if (vm.listViewId == 0) {
    //get default list view
    //http://localhost:7575/api/v8/DataListView/default/TestWidgetDataList
    return window.$gz.api
      .get("DataListView/default/" + vm.dataListKey)
      .then(res => {
        if (res.error != undefined) {
          throw res.error;
        } else {
          vm.effectiveListView = JSON.parse(res.data);
          vm.obj.name = vm.lt("FilterUnsaved");
        }
      });
  } else {
    //listview has an id value
    return window.$gz.api.get("DataListView/" + vm.listViewId).then(res => {
      if (res.error != undefined) {
        throw res.error;
      } else {
        vm.effectiveListView = JSON.parse(res.data.listView);
        vm.obj.public = res.data.public;
        vm.obj.name = res.data.name;
      }
    });
  }
}

////////////////////
//
function initDataObject(vm) {
  //console.log("called initDataObject");

  if (vm.effectiveListView == null) {
    throw "ay-data-list::initDataObject - effectiveListView is not set";
  }
  if (vm.fieldDefinitions == null) {
    throw "ay-data-list::initDataObject - fieldDefinitions are not set";
  }

  var ret = [];

  //Pass 1, iterate the listview first
  for (var i = 0; i < vm.effectiveListView.length; i++) {
    var lvItem = vm.effectiveListView[i];

    var fld = window.$gz._.find(vm.fieldDefinitions, ["fieldKey", lvItem.fld]);
    var o = {
      key: fld.fieldKey,
      title: vm.lt(fld.ltKey),
      include: true,
      isFilterable: fld.isFilterable,
      isSortable: fld.isSortable,
      enumType: fld.enumType,
      uiFieldDataType: fld.uiFieldDataType,
      isCustomField: fld.isCustomField,
      sort: lvItem.sort || null,
      filter: lvItem.filter || { any: false, items: [] },
      tempFilterOperator: null,
      tempFilterToken: null,
      tempFilterValue: null
    };

    //If it's a tag and it's not been set yet it needs to have an empty array to stat with for the picker
    if (o.uiFieldDataType == 9 && o.tempFilterValue == null) {
      o.tempFilterValue = [];
    }

    //Add display text for filter item (same as in addFilterCondition)
    for (var j = 0; j < o.filter.items.length; j++) {
      var fi = o.filter.items[j];
      fi.display = getDisplayForFilter(
        vm,
        o.uiFieldDataType,
        fi.op,
        fi.value,
        o.enumType
      );
    }

    ret.push(o);
  }

  //Pass 2, remaining fields not already dealt with
  //debugger;
  for (var i = 0; i < vm.fieldDefinitions.length; i++) {
    var fld = vm.fieldDefinitions[i];
    //skip over the default column
    if (fld.fieldKey == "df") {
      continue;
    }
    //is this field already in ret array?
    if (null == window.$gz._.find(ret, ["key", fld.fieldKey])) {
      //nope, so add it
      var o = {
        key: fld.fieldKey,
        title: vm.lt(fld.ltKey),
        include: false,
        isFilterable: fld.isFilterable,
        isSortable: fld.isSortable,
        enumType: fld.enumType,
        uiFieldDataType: fld.uiFieldDataType,
        isCustomField: fld.isCustomField,
        sort: null,
        filter: { any: false, items: [] },
        tempFilterOperator: null,
        tempFilterToken: null,
        tempFilterValue: null
      };
      //If it's a tag and it's not been set yet it needs to have an empty array to stat with for the picker
      if (o.uiFieldDataType == 9 && o.tempFilterValue == null) {
        o.tempFilterValue = [];
      }
      ret.push(o);
    }
  }
  vm.obj.editView = ret;

  if (window.$gz.errorHandler.devMode) {
    if (vm.obj.editView.length != vm.fieldDefinitions.length - 1) {
      throw "ay-data-list-view::initDataObject - working array length not equal to total field definition length";
    }
  }
  return Promise.resolve();

  //eoc
}

//////////////////////////////////////////////////////////
//
// Ensures localized enum lists are available pre-cached
//
function fetchEnums(vm) {
  //build an array of all enums then execute method
  var enumKeys = [];
  for (var i = 0; i < vm.fieldDefinitions.length; i++) {
    var fld = vm.fieldDefinitions[i];
    if (fld.uiFieldDataType == 10) {
      enumKeys.push(fld.enumType);
    }
  }
  if (enumKeys.length > 0) {
    // console.log("fetchEnums::calling fetchenumlist for:");
    // console.log(enumKeys);
    return window.$gz.enums.fetchEnumList(enumKeys);
  }
  return Promise.resolve();
}

//////////////////////////////////////////////////////////
//
// Convert working object to actual listView
//
function updateEditedListView(vm) {
  //turn the obj.editView settings into an actual listview
  //compare it with the effectiveListView to see if there are any changes between the two
  //set the form to dirty if there are changes and can save
  //this.formState.dirty = true;
  //this way user can build their way back to the same view and then no need to save if no changes
  //build an array of all enums then execute method
}

//////////////////////////////////////////////////////////
//
// Convert filter properties to localized / displayable
// used when making new filter and loading existing
//
function getDisplayForFilter(
  vm,
  uiFieldDataType,
  filterOperator,
  filterValue,
  enumType
) {
  //BLANKS FILTER
  if (filterOperator == "=" && filterValue == "*NULL*") {
    return window.$gz._.find(vm.pickLists.stringFilterOperators, {
      id: "*NOVALUE*"
    }).name;
  }
  // NONBLANKS FILTER
  if (filterOperator == "!=" && filterValue == "*NULL*") {
    return window.$gz._.find(vm.pickLists.stringFilterOperators, {
      id: "*HASVALUE*"
    }).name;
  }

  //DATE RELATIVE TOKEN FILTER
  if (uiFieldDataType === 1 && filterValue[0] == "*") {
    var valueDisplay = window.$gz._.find(vm.pickLists.dateFilterTokens, {
      id: filterValue
    }).name;
    var opDisplay = filterOperator;
    return filterOperator + " " + valueDisplay;
  }

  //VALUE FILTER
  //Nothing more to do if there isn't both a value AND an operator at this point
  if (filterOperator == null || filterValue == null) {
    if (window.$gz.errorHandler.devMode()) {
      throw "ay-data-list-view::getDisplayForFilter Value filter missing one ore more of Operator, Value";
    }
    return "";
  }

  var valueDisplay = "selected value";
  switch (uiFieldDataType) {
    case 1: //date localize
      valueDisplay = window.$gz.locale.utcDateToShortDateAndTimeLocalized(
        filterValue
      );
      break;
    case 8: //currency localize
      valueDisplay = window.$gz.locale.currencyLocalized(filterValue);
      break;
    case 7: //decimal localize
      valueDisplay = window.$gz.locale.decimalLocalized(filterValue);
      break;
    case 6: //BOOL localize
      //debugger;
      var ltKey = filterValue ? "True" : "False";
      valueDisplay = vm.lt(ltKey);
      break;
    case 10: //ENUM localize
      valueDisplay = window.$gz.enums.get(enumType, filterValue);
      break;
    default:
      valueDisplay = filterValue;
      break;
  }

  //Operator
  var opDisplay = window.$gz._.find(vm.pickLists.stringFilterOperators, {
    id: filterOperator
  }).name;

  return opDisplay + ' "' + valueDisplay + '"';

  //eoc
}

//////////////////////////////////////////////////////////
//
// Convert editedList view to real list view and return
//
function generateListViewFromEdited(vm) {
  //obj: { editView: [], name: "", public: true },
  if (vm.obj.editView == null || vm.obj.editView.length == 0) {
    return;
  }

  var ret = [];

  for (var i = 0; i < vm.obj.editView.length; i++) {
    var ev = vm.obj.editView[i];
    if (!ev.include) {
      continue;
    }
    var o = {
      fieldKey: ev.key
    };
    if (ev.sort != null) {
      o.sort = ev.sort;
    }
    if (ev.filter && ev.filter.items && ev.filter.items.length > 0) {
      var f = {
        items: []
      };
      if (ev.filter.any) {
        f.any = true;
      }
      for (var j = 0; j < ev.filter.items; j++) {
        f.items.push({
          op: ev.filter.items[j].op,
          value: ev.filter.items[j].value
        });
      }
    }
    ret.push(o);
  }
  return ret;
  //eoc
}

/////////////END OF FORM//////////////////

/*


















         public const string OpEquality = "=";
        public const string OpGreaterThan = ">";
        public const string OpGreaterThanOrEqualTo = ">=";
        public const string OpLessThan = "<";
        public const string OpLessThanOrEqualTo = "<=";
        public const string OpNotEqual = "!=";
        public const string OpNotLike = "!%";
        public const string OpStartsWith = "%-";
        public const string OpEndsWith = "-%";
        public const string OpContains = "-%-";
        public const string OpNotContains = "!-%-";

        =-=-=-=-
         public const string TokenYesterday = "{[yesterday]}";
                public const string TokenToday = "{[today]}";
                public const string TokenTomorrow = "{[tomorrow]}";
                public const string TokenLastWeek = "{[lastweek]}";
                public const string TokenThisWeek = "{[thisweek]}";
                public const string TokenNextWeek = "{[nextweek]}";
                public const string TokenLastMonth = "{[lastmonth]}";
                public const string TokenThisMonth = "{[thismonth]}";
                public const string TokenNextMonth = "{[nextmonth]}";
                public const string TokenFourteenDayWindow = "{[14daywindow]}";
                public const string TokenPast = "{[past]}";
                public const string TokenFuture = "{[future]}";
                public const string TokenLastYear = "{[lastyear]}";
                public const string TokenThisYear = "{[thisyear]}";
                public const string TokenInTheLast3Months = "{[last3months]}";
                public const string TokenInTheLast6Months = "{[last6months]}";
                public const string TokenInTheLastYear = "{[lastcalendaryear]}";

                //More business time frames

                public const string TokenYearToDate = "{[yeartodate]}";

                public const string TokenPast90Days = "{[past90days]}";
                public const string TokenPast30Days = "{[past30days]}";
                public const string TokenPast24Hours = "{[past24hours]}";

                //Months THIS year
                public const string TokenJanuary = "{[january]}";
                public const string TokenFebruary = "{[february]}";
                public const string TokenMarch = "{[march]}";
                public const string TokenApril = "{[april]}";
                public const string TokenMay = "{[may]}";
                public const string TokenJune = "{[june]}";
                public const string TokenJuly = "{[july]}";
                public const string TokenAugust = "{[august]}";
                public const string TokenSeptember = "{[september]}";
                public const string TokenOctober = "{[october]}";
                public const string TokenNovember = "{[november]}";
                public const string TokenDecember = "{[december]}";



                   public enum UiFieldDataType : int
    {
        NoType = 0,
        DateTime = 1,
        Date = 2,
        Time = 3,
        Text = 4,
        Integer = 5,
        Bool = 6,
        Decimal = 7,
        Currency = 8,
        Tags = 9,
        Enum = 10,
        EmailAddress = 11,
        HTTP = 12,
        InternalId = 13

    }
       */
</script>
