<template>
  <v-container>
    <gz-report-selector ref="reportSelector"></gz-report-selector>
    <v-row v-if="formState.ready">
      <v-col>
        <v-form ref="form">
          <v-row>
            <gz-error :errorBoxMessage="formState.errorBoxMessage"></gz-error>
            <v-col cols="12" sm="6" lg="4" xl="3">
              <v-text-field
                v-model="obj.name"
                :readonly="formState.readOnly"
                clearable
                @click:clear="fieldValueChanged('name')"
                :counter="255"
                :label="$ay.t('WidgetName')"
                :rules="[
                  form().max255(this, 'name'),
                  form().required(this, 'name')
                ]"
                :error-messages="form().serverErrors(this, 'name')"
                ref="name"
                :data-cy="!!$ay.dev ? 'name' : false"
                @input="fieldValueChanged('name')"
              ></v-text-field>
            </v-col>
            <v-col
              v-if="form().showMe(this, 'Serial')"
              cols="12"
              sm="6"
              lg="4"
              xl="3"
            >
              <v-text-field
                v-model="obj.serial"
                :readonly="true"
                :label="$ay.t('WidgetSerial')"
                :data-cy="!!$ay.dev ? 'serial' : false"
              ></v-text-field>
            </v-col>
            <v-col
              v-if="form().showMe(this, 'Count')"
              cols="12"
              sm="6"
              lg="4"
              xl="3"
            >
              <v-text-field
                v-model="obj.count"
                :readonly="formState.readOnly"
                clearable
                @click:clear="fieldValueChanged('count')"
                :counter="10"
                :label="$ay.t('WidgetCount')"
                ref="count"
                :data-cy="!!$ay.dev ? 'count' : false"
                :rules="[form().integerValid(this, 'count')]"
                :error-messages="form().serverErrors(this, 'count')"
                @input="fieldValueChanged('count')"
                type="number"
              ></v-text-field>
            </v-col>

            <v-col
              v-if="form().showMe(this, 'DollarAmount')"
              cols="12"
              sm="6"
              lg="4"
              xl="3"
            >
              <gz-currency
                v-model="obj.dollarAmount"
                :readonly="formState.readOnly"
                :label="$ay.t('WidgetDollarAmount')"
                ref="dollarAmount"
                :data-cy="!!$ay.dev ? 'dollarAmount' : false"
                :rules="[
                  form().decimalValid(this, 'dollarAmount'),
                  form().required(this, 'dollarAmount')
                ]"
                :error-messages="form().serverErrors(this, 'dollarAmount')"
                @input="fieldValueChanged('dollarAmount')"
              ></gz-currency>
            </v-col>

            <v-col cols="12" sm="6" lg="4" xl="3">
              <gz-date-time-picker
                :label="$ay.t('WidgetStartDate')"
                v-model="obj.startDate"
                :readonly="formState.readOnly"
                ref="startDate"
                testId="startDate"
                :error-messages="form().serverErrors(this, 'startDate')"
                @input="fieldValueChanged('startDate')"
              ></gz-date-time-picker>
            </v-col>

            <v-col cols="12" sm="6" lg="4" xl="3">
              <gz-date-time-picker
                :label="$ay.t('WidgetEndDate')"
                :rules="[form().datePrecedence(this, 'startDate', 'endDate')]"
                :error-messages="form().serverErrors(this, 'endDate')"
                v-model="obj.endDate"
                :readonly="formState.readOnly"
                ref="endDate"
                testId="endDate"
                @input="fieldValueChanged('endDate')"
              ></gz-date-time-picker>
            </v-col>
            <v-col
              v-if="form().showMe(this, 'Active')"
              cols="12"
              sm="6"
              lg="4"
              xl="3"
            >
              <v-checkbox
                v-model="obj.active"
                :readonly="formState.readOnly"
                :label="$ay.t('Active')"
                ref="active"
                :data-cy="!!$ay.dev ? 'active' : false"
                :error-messages="form().serverErrors(this, 'active')"
                @change="fieldValueChanged('active')"
              ></v-checkbox>
            </v-col>

            <v-col
              v-if="form().showMe(this, 'UserId')"
              cols="12"
              sm="6"
              lg="4"
              xl="3"
            >
              <gz-pick-list
                :ayaType="ayaType().User"
                :showEditIcon="true"
                v-model="obj.userId"
                :readonly="formState.readOnly"
                :label="$ay.t('User')"
                ref="userid"
                :data-cy="!!$ay.dev ? 'userid' : false"
                :error-messages="form().serverErrors(this, 'userid')"
                @input="fieldValueChanged('userid')"
              ></gz-pick-list>
            </v-col>

            <v-col
              v-if="form().showMe(this, 'UserType')"
              cols="12"
              sm="6"
              lg="4"
              xl="3"
            >
              <v-select
                v-model="obj.userType"
                :items="selectLists.usertypes"
                item-text="name"
                item-value="id"
                :readonly="formState.readOnly"
                :label="$ay.t('UserType')"
                ref="usertype"
                :data-cy="!!$ay.dev ? 'usertype' : false"
                :rules="[form().integerValid(this, 'usertype')]"
                :error-messages="form().serverErrors(this, 'usertype')"
                @input="fieldValueChanged('usertype')"
              ></v-select>
            </v-col>

            <v-col v-if="form().showMe(this, 'Notes')" cols="12">
              <v-textarea
                v-model="obj.notes"
                :readonly="formState.readOnly"
                :label="$ay.t('WidgetNotes')"
                :error-messages="form().serverErrors(this, 'notes')"
                ref="notes"
                :data-cy="!!$ay.dev ? 'notes' : false"
                @input="fieldValueChanged('notes')"
                auto-grow
                clearable
              ></v-textarea>
            </v-col>

            <v-col v-if="form().showMe(this, 'Tags')" cols="12">
              <gz-tag-picker
                v-model="obj.tags"
                :readonly="formState.readOnly"
                ref="tags"
                :data-cy="!!$ay.dev ? 'tags' : false"
                :error-messages="form().serverErrors(this, 'tags')"
                @input="fieldValueChanged('tags')"
              ></gz-tag-picker>
            </v-col>

            <v-col cols="12">
              <gz-custom-fields
                v-model="obj.customFields"
                :formKey="formCustomTemplateKey"
                :readOnly="formState.readOnly"
                :parentVM="this"
                ref="customFields"
                :data-cy="!!$ay.dev ? 'customFields' : false"
                :error-messages="form().serverErrors(this, 'customFields')"
                @input="fieldValueChanged('customFields')"
              ></gz-custom-fields>
            </v-col>
          </v-row>
        </v-form>
      </v-col>
    </v-row>
  </v-container>
</template>

<script>
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*  Xeslint-disable    */
//v-bind:value.sync="obj.customFields"
////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Illegal1 = O0
const FORM_KEY = "widget-edit";
const API_BASE_URL = "Widget/";
const FORM_CUSTOM_TEMPLATE_KEY = "Widget";

export default {
  created() {
    let vm = this;
    initForm(vm)
      .then(() => {
        vm.rights = window.$gz.role.getRights(window.$gz.type.Widget);
        vm.formState.ready = true;
        window.$gz.eventBus.$on("menu-click", clickHandler);
        //id 0 means create a new record don't load one
        if (vm.$route.params.recordid != 0) {
          vm.getDataFromApi(vm.$route.params.recordid);
        } else {
          //setup for new record
          let readOnly = !vm.rights.change;
          //Update the form status
          window.$gz.form.setFormState({
            vm: vm,
            dirty: false,
            valid: true,
            loading: false,
            readOnly: readOnly
          });

          // //bugbug WTF?  This doesn't make sense, if it's an attempt to hide delete button then that's wrong
          // //it's a new record so it can't be deleted so...
          // vm.rights.delete = false;
          generateMenu(vm);
        }
      })
      .catch(err => {
        vm.formState.ready = true;
        window.$gz.errorHandler.handleFormError(err, vm);
      });
  },
  beforeRouteUpdate(to, from, next) {
    //This triggers a fetch of the data when the ID value changes on the route
    //which happens on duplicate, submit new record and change of active record id (backward nav/forward nav etc)
    if (to.params.recordid != 0) {
      this.getDataFromApi(to.params.recordid);
    }
    next();
    // react to route changes...
    // don't forget to call next()
  },
  beforeRouteLeave(to, from, next) {
    //let vm = this;
    if (this.formState.dirty && !JUST_DELETED) {
      window.$gz.dialog.confirmLeaveUnsaved().then(dialogResult => {
        if (dialogResult == true) {
          next();
        } else {
          next(false);
        }
      });
    } else {
      next();
    }
  },
  beforeDestroy() {
    window.$gz.eventBus.$off("menu-click", clickHandler);
  },
  components: {},
  data() {
    return {
      formCustomTemplateKey: FORM_CUSTOM_TEMPLATE_KEY,
      selectLists: {
        usertypes: []
      },
      obj: {
        //IMPORTANT NOTE: Fields that are NON NULLABLE in the schema for the table but *are* hideable **MUST** have a default value set here or else there will be no way to save the record
        //I.E. Serial, usertype fields
        id: 0,
        concurrencyToken: 0,
        name: null,
        serial: 0,
        dollarAmount: null,
        active: null,
        userType: 0,
        startDate: null,
        endDate: null,
        notes: null,
        count: null,
        customFields: "{}",
        tags: [],
        userId: null
      },
      formState: {
        ready: false,
        dirty: false,
        valid: true,
        readOnly: false,
        loading: true,
        errorBoxMessage: null,
        appError: null,
        serverError: {}
      },
      rights: window.$gz.role.defaultRightsObject()
    };
  },
  //WATCHERS
  watch: {
    formState: {
      handler: function(val) {
        //,oldval is available here too if necessary
        if (this.formState.loading) {
          return;
        }

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

        //enable / disable duplicate / new button
        if (!val.dirty && val.valid && !val.readOnly) {
          window.$gz.eventBus.$emit(
            "menu-enable-item",
            FORM_KEY + ":duplicate"
          );
          window.$gz.eventBus.$emit("menu-enable-item", FORM_KEY + ":new");
        } else {
          window.$gz.eventBus.$emit(
            "menu-disable-item",
            FORM_KEY + ":duplicate"
          );
          window.$gz.eventBus.$emit("menu-disable-item", FORM_KEY + ":new");
        }
      },
      deep: true
    }
  },
  computed: {
    canSave: function() {
      return this.formState.valid && this.formState.dirty;
    },
    canDuplicate: function() {
      return this.formState.valid && !this.formState.dirty;
    }
  },
  methods: {
    ayaType: function() {
      return window.$gz.type;
    },
    form() {
      return window.$gz.form;
    },
    fieldValueChanged(ref) {
      if (!this.formState.loading && !this.formState.readOnly) {
        window.$gz.form.fieldValueChanged(this, ref);
      }
    },
    getDataFromApi(recordId) {
      let vm = this;
      vm.formState.loading = true;
      if (!recordId) {
        throw FORM_KEY + "::getDataFromApi -> Missing recordID!";
      }
      let url = API_BASE_URL + recordId;

      window.$gz.form.deleteAllErrorBoxErrors(vm);

      window.$gz.api
        .get(url)
        .then(res => {
          if (res.error != undefined) {
            //Not found?
            if (res.error.code == "2010") {
              //notify not found error then navigate backwards
              window.$gz.eventBus.$emit(
                "notify-error",
                vm.$ay.t("ErrorAPI2010")
              );
              // navigate backwards
              window.$gz._.delay(function() {
                vm.$router.go(-1);
              }, 2000);
            }
            vm.formState.serverError = res.error;
            window.$gz.form.setErrorBoxErrors(vm);
          } else {
            vm.obj = res.data;

            //Update the form status
            window.$gz.form.setFormState({
              vm: vm,
              dirty: false,
              valid: true,
              loading: false,
              readOnly: res.readOnly ? true : false
            });
            //modify the menu as necessary
            generateMenu(vm);
          }
        })
        .catch(function handleGetDataFromAPIError(error) {
          //Update the form status
          window.$gz.form.setFormState({
            vm: vm,
            loading: false
          });
          window.$gz.errorHandler.handleFormError(error, vm);
        });
    },
    submit() {
      let vm = this;
      if (vm.canSave) {
        vm.formState.loading = true;
        let url = API_BASE_URL + vm.$route.params.recordid;

        //clear any errors vm might be around from previous submit
        window.$gz.form.deleteAllErrorBoxErrors(vm);
        window.$gz.api
          .upsert(url, vm.obj)
          .then(res => {
            vm.formState.loading = false;
            if (res.error != undefined) {
              vm.formState.serverError = res.error;
              window.$gz.form.setErrorBoxErrors(vm);
            } else {
              //Logic for detecting if a post or put: if id then it was a post, if no id then it was a put
              if (res.data.id) {
                //Handle "post" of new record (CREATE)

                //change url to new record in history
                //NOTE: will not cause a page re-render, almost nothing does unless forced with a KEY property or using router.GO()
                //but will trigger navigation guard beforeRouteUpdate which we use here in this form to fetch data freshly
                vm.$router.replace(
                  vm.$route.fullPath.slice(0, -1) + res.data.id
                );
              } else {
                //Handle "put" of an existing record (UPDATE)
                vm.obj.concurrencyToken = res.data.concurrencyToken;
                window.$gz.form.setFormState({
                  vm: vm,
                  dirty: false
                });
              }
            }
          })
          .catch(function handleSubmitError(error) {
            debugger;
            vm.formState.loading = false;
            window.$gz.errorHandler.handleFormError(error, vm);
          });
      }
    },
    remove() {
      let vm = this;
      window.$gz.dialog.confirmDelete().then(dialogResult => {
        if (dialogResult == true) {
          //do the delete
          vm.formState.loading = true;
          //No need to delete a new record, just abandon it...
          if (vm.$route.params.recordid == 0) {
            //this should not get offered for delete but to be safe and clear just in case:
            JUST_DELETED = true;
            // navigate backwards
            vm.$router.go(-1);
          } else {
            let url = API_BASE_URL + vm.$route.params.recordid;

            window.$gz.form.deleteAllErrorBoxErrors(vm);
            window.$gz.api
              .remove(url)
              .then(res => {
                if (res.error != undefined) {
                  vm.formState.serverError = res.error;
                  window.$gz.form.setErrorBoxErrors(vm);
                } else {
                  //workaround to prevent warning about leaving dirty record
                  //For some reason I couldn't just reset isdirty in formstate
                  JUST_DELETED = true;
                  // navigate backwards
                  vm.$router.go(-1);
                }
              })
              .catch(function handleGetDataFromAPIError(error) {
                //Update the form status
                window.$gz.form.setFormState({
                  vm: vm,
                  loading: false
                });
                window.$gz.errorHandler.handleFormError(error, vm);
              });
          }
        }
      });
    },
    duplicate() {
      let vm = this;
      if (vm.canDuplicate && vm.$route.params.recordid != 0) {
        vm.formState.loading = true;

        let url = API_BASE_URL + "duplicate/" + vm.$route.params.recordid;

        //clear any errors vm might be around from previous submit
        window.$gz.form.deleteAllErrorBoxErrors(vm);
        window.$gz.api
          .duplicate(url)
          .then(res => {
            // debugger;
            vm.formState.loading = false;
            if (res.error != undefined) {
              vm.formState.serverError = res.error;
              window.$gz.form.setErrorBoxErrors(vm);
            } else {
              //Navigate to new record
              vm.$router.push(
                window.$gz.api.replaceAfterLastSlash(
                  vm.$route.fullPath,
                  res.data.id
                )
              );
            }
          })
          .catch(function handleDuplicateError(error) {
            vm.formState.loading = false;
            window.$gz.errorHandler.handleFormError(error, vm);
          });
      }
    }
  }
};

/////////////////////////////
//
//
function clickHandler(menuItem) {
  if (!menuItem) {
    return;
  }
  let 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 "new":
        m.vm.$router.push({
          name: "widget-edit",
          params: { recordid: 0, new: true }
        });
        break;
      case "duplicate":
        m.vm.duplicate();
        break;
      case "report":
        if (m.id != null) {
          //last report selected
          m.vm.$router.push({
            name: "ay-report",
            params: { recordid: m.id, ayatype: window.$gz.type.Widget }
          });
        } else {
          //general report selector chosen
          m.vm.$refs.reportSelector.open().then(res => {
            //if null for no selection
            //just bail out
            if (res == null) {
              return;
            }
            //persist last report selected
            window.$gz.form.setLastReport(FORM_KEY, res);

            //Now open the report viewer...
            m.vm.$router.push({
              name: "ay-report",
              params: { recordid: res.id, ayatype: window.$gz.type.Widget }
            });
          });
        }
        break;
      default:
        window.$gz.eventBus.$emit(
          "notify-warning",
          FORM_KEY + "::context click: [" + m.key + "]"
        );
    }
  }
}

//////////////////////
//
//
function generateMenu(vm) {
  let menuOptions = {
    isMain: false,
    icon: "fa-splotch",
    title: vm.$ay.t("Widget"),
    helpUrl: "form-widget",
    formData: {
      ayaType: window.$gz.type.Widget,
      recordId: vm.$route.params.recordid,
      formCustomTemplateKey: FORM_CUSTOM_TEMPLATE_KEY
    },
    menuItems: []
  };

  if (vm.rights.change) {
    menuOptions.menuItems.push({
      title: vm.$ay.t("Save"),
      icon: "fa-save",
      surface: true,
      key: FORM_KEY + ":save",
      vm: vm
    });
  }

  if (vm.rights.delete && vm.$route.params.recordid != 0) {
    menuOptions.menuItems.push({
      title: vm.$ay.t("Delete"),
      icon: "fa-trash-alt",
      surface: true,
      key: FORM_KEY + ":delete",
      vm: vm
    });
  }

  //STUB REPORTS
  //Report not Print, print is a further option
  menuOptions.menuItems.push({
    title: vm.$ay.t("Report"),
    icon: "fa-file-alt",
    key: FORM_KEY + ":report",
    vm: vm
  });

  //get last report selected
  let lastReport = window.$gz.form.getLastReport(FORM_KEY);
  if (lastReport != null) {
    menuOptions.menuItems.push({
      title: lastReport.name,
      icon: "fa-file-alt",
      key: FORM_KEY + ":report:" + lastReport.id,
      vm: vm
    });
  }

  //todo: get the last used report from the vuex form state and
  //insert it here if it exists.
  //was going to do multiple but that's a lot of fuckery and space eating

  if (vm.rights.change) {
    menuOptions.menuItems.push({
      title: vm.$ay.t("New"),
      icon: "fa-plus",
      key: FORM_KEY + ":new",
      vm: vm
    });
  }

  if (vm.rights.change) {
    menuOptions.menuItems.push({
      title: vm.$ay.t("Duplicate"),
      icon: "fa-clone",
      key: FORM_KEY + ":duplicate",
      vm: vm
    });
  }

  window.$gz.eventBus.$emit("menu-change", menuOptions);
}

let JUST_DELETED = false;

/////////////////////////////////
//
//
function initForm(vm) {
  return new Promise(function(resolve, reject) {
    (async function() {
      try {
        await fetchTranslatedText(vm);
        await window.$gz.formCustomTemplate.get(FORM_CUSTOM_TEMPLATE_KEY);
        await populateSelectionLists(vm);
      } catch (err) {
        reject(err);
      }
      resolve();
    })();
  });
}

//////////////////////////////////////////////////////////
//
// Ensures UI translated text is available
//
function fetchTranslatedText(vm) {
  return window.$gz.translation.fetch([
    "Widget",
    "WidgetName",
    "WidgetSerial",
    "WidgetDollarAmount",
    "WidgetCount",
    "User",
    "UserType",
    "WidgetStartDate",
    "WidgetEndDate",
    "WidgetNotes",
    "WidgetCustom1",
    "WidgetCustom2",
    "WidgetCustom3",
    "WidgetCustom4",
    "WidgetCustom5",
    "WidgetCustom6",
    "WidgetCustom7",
    "WidgetCustom8",
    "WidgetCustom9",
    "WidgetCustom10",
    "WidgetCustom11",
    "WidgetCustom12",
    "WidgetCustom13",
    "WidgetCustom14",
    "WidgetCustom15",
    "WidgetCustom16"
  ]);
}

//////////////////////
//
//
function populateSelectionLists(vm) {
  //ensure the pick lists required are pre-fetched
  return window.$gz.enums.fetchEnumList("usertype").then(() => {
    vm.selectLists.usertypes = window.$gz.enums.getSelectionList("usertype");
  });
}
</script>

<style></style>
