<template>
  <div v-if="templateHasVisibleCustomFields()">
    <span class="v-label v-label--active theme--light">
      {{ lt("ObjectCustomFieldCustomGrid") }}
    </span>
    <div>
      <v-row align-center justify-left row wrap>
        <template v-for="item in this.$store.state.formCustomTemplate[formKey]">
          <v-col
            v-if="item.type"
            :key="item.fld"
            cols="12"
            sm="6"
            lg="4"
            xl="3"
            px-2
          >
            <!-- DATETIME  -->
            <div v-if="item.type === 1">
              <gz-date-time-picker
                v-model="_self[item.dataKey]"
                :readonly="readOnly"
                :label="lt(item.fld)"
                :ref="item.fld"
                :error-messages="form().serverErrors(parentVM, item.fld)"
                :rules="[
                  form().customFieldsCheck(parentVM, item, _self, lt(item.fld))
                ]"
              ></gz-date-time-picker>
            </div>

            <!-- DATE -->
            <div v-else-if="item.type === 2">
              <gz-date-picker
                v-model="_self[item.dataKey]"
                :readonly="readOnly"
                :label="lt(item.fld)"
                :ref="item.fld"
                :error-messages="form().serverErrors(parentVM, item.fld)"
                :rules="[
                  form().customFieldsCheck(parentVM, item, _self, lt(item.fld))
                ]"
              ></gz-date-picker>
            </div>
            <!-- TIME -->
            <div v-else-if="item.type === 3">
              <gz-time-picker
                v-model="_self[item.dataKey]"
                :readonly="readOnly"
                :label="lt(item.fld)"
                :ref="item.fld"
                :error-messages="form().serverErrors(parentVM, item.fld)"
                :rules="[
                  form().customFieldsCheck(parentVM, item, _self, lt(item.fld))
                ]"
              ></gz-time-picker>
            </div>
            <!-- TEXT -->
            <div v-else-if="item.type === 4">
              <v-textarea
                v-model="_self[item.dataKey]"
                :readonly="readOnly"
                :label="lt(item.fld)"
                :ref="item.fld"
                :error-messages="form().serverErrors(parentVM, item.fld)"
                :rules="[
                  form().customFieldsCheck(parentVM, item, _self, lt(item.fld))
                ]"
                auto-grow
                clearable
              ></v-textarea>
            </div>
            <!-- INTEGER -->
            <div v-else-if="item.type === 5">
              <v-text-field
                v-model="_self[item.dataKey]"
                :readonly="readOnly"
                :label="lt(item.fld)"
                :ref="item.fld"
                :error-messages="form().serverErrors(parentVM, item.fld)"
                :rules="[
                  form().customFieldsCheck(parentVM, item, _self, lt(item.fld))
                ]"
                clearable
                :counter="10"
                type="number"
                step="none"
              ></v-text-field>
            </div>
            <!-- BOOL -->
            <div v-else-if="item.type === 6">
              <v-checkbox
                v-model="_self[item.dataKey]"
                :readonly="readOnly"
                :label="lt(item.fld)"
                :ref="item.fld"
                :error-messages="form().serverErrors(parentVM, item.fld)"
                :rules="[
                  form().customFieldsCheck(parentVM, item, _self, lt(item.fld))
                ]"
              ></v-checkbox>
            </div>
            <!-- DECIMAL -->
            <div v-else-if="item.type === 7">
              <gz-decimal
                v-model="_self[item.dataKey]"
                :readonly="readOnly"
                :label="lt(item.fld)"
                :ref="item.fld"
                :error-messages="form().serverErrors(parentVM, item.fld)"
                :rules="[
                  form().customFieldsCheck(parentVM, item, _self, lt(item.fld))
                ]"
              ></gz-decimal>
            </div>
            <!-- CURRENCY -->
            <div v-else-if="item.type === 8">
              <gz-currency
                v-model="_self[item.dataKey]"
                :readonly="readOnly"
                :label="lt(item.fld)"
                :ref="item.fld"
                :error-messages="form().serverErrors(parentVM, item.fld)"
                :rules="[
                  form().customFieldsCheck(parentVM, item, _self, lt(item.fld))
                ]"
              ></gz-currency>
            </div>
            <div v-else>
              <span class="error"
                >UNKNOWN CUSTOM CONTROL TYPE: {{ item.type }}</span
              >
            </div>
          </v-col>
        </template>
      </v-row>
    </div>
  </div>
</template>
<script>
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*  XXXeslint-disable    */
////////////////////////////////////////////////////////////////////////////////////////////////////////////

export default {
  data() {
    return {};
  },

  props: {
    value: {
      default: "{}",
      type: String
    },
    formKey: String, //used to grab template from store
    readOnly: Boolean,
    parentVM: Object
  },

  methods: {
    lt: function(ltkey) {
      return window.$gz.locale.get(ltkey);
    },
    form() {
      //nothing
      return window.$gz.form;
    },
    onChange(ref) {
      if (
        !this.parentVM.formState.loading &&
        !this.parentVM.formState.readOnly
      ) {
        window.$gz.form.onChange(this.parentVM, ref);
      }
    },
    templateHasVisibleCustomFields() {
      var template = this.$store.state.formCustomTemplate[this.formKey];
      if (template == undefined) {
        return false;
      }
      //iterate template and see if it has any custom fields set to display
      return window.$gz._.find(template, "type") != undefined;
    },
    GetValueForField: function(dataKey) {
      if (!this.value) {
        return null;
      }

      //get the data out of the JSON string value
      var cData = JSON.parse(this.value);

      //Custom field types can be changed by the user and cause old entered data to be invalid for that field type
      //Here we need to take action if the data is of an incompatible type for the control field type and attempt to coerce or simply nullify if not co-ercable the data
      //  - CURRENT TEXT fields could handle any data so they don't need to be changed
      //	- CURRENT BOOL fields can only handle empty or true false so they would need to be set null
      //	- CURRENT TIME, DATE, DATETIME are pretty specific but all use a datetime string so any value not datetime like should be nulled
      //  - CURRENT NUMBER, CURRENCY are also pretty specific but easy to identify if not fully numeric and then sb nulled or attempt to convert then null if not

      //Get the field data type
      //https://lodash.com/docs#find
      var ctrlType = window.$gz._.find(
        this.$store.state.formCustomTemplate[this.formKey],
        ["dataKey", dataKey]
      ).type;

      //First get current value for the data that came from the server
      var ret = cData[dataKey];
      //Only process if value is non-null since all control types can handle null
      if (ret != null) {
        //check types that matter
        /*thes are all types, not necessarily all custom field types
           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
        */
        switch (ctrlType) {
          //DateLike?
          case 1:
          case 2:
          case 3:
            //can it be parsed into a date using the same library as the components use?
            if (!window.$gz.DateTime.fromISO(ret).isValid) {
              ret = null;
            }
            break;
          case 6:
            //if it's not already a boolean
            if (!window.$gz._.isBoolean(ret)) {
              //it's not a bool and it's not null, it came from some other data type,
              //perhaps though, it's a truthy string so check for that before giving up and nulling
              if (window.$gz._.isString(ret)) {
                ret = window.$gz.util.stringToBoolean(ret);
                break;
              }
              //The number 1?
              if (ret === 1) {
                ret = true;
                break;
              }
              //The number 0?
              if (ret === 0) {
                ret = false;
                break;
              }
            }
            break;
          case 8:
          case 7:
            if (!window.$gz._.isNumber(ret)) {
              ret = window.$gz.util.stringToFloat(ret);

              break;
            }
            break;
        }
      }

      return ret;
    },
    SetValueForField: function(dataKey, newValue) {
      //Get the current data out of the json string value
      //
      var cData = JSON.parse(this.value);
      if (!window.$gz._.has(cData, dataKey)) {
        cData[dataKey] = null;
      }

      //handle null or undefined
      if (newValue === null || newValue === undefined) {
        cData[dataKey] = null;
      } else {
        //then set item in the cData
        cData[dataKey] = newValue.toString();
      }

      //emit the new data so it syncs with the parent source
      var ret = JSON.stringify(cData);
      //THis is absolutely required or it won't save any changes, no idea why though
      this.$emit("update:value", ret);
      //this.$emit("input", ret); //always in UTC
      //this triggers the onchange routine in the parent form
      //so that the dirty checking works
      this.$emit("change", ret);
    }
  },
  computed: {
    c1: {
      get: function() {
        return this.GetValueForField("c1");
      },
      set: function(newValue) {
        this.SetValueForField("c1", newValue);
      }
    },
    c2: {
      get: function() {
        return this.GetValueForField("c2");
      },
      set: function(newValue) {
        this.SetValueForField("c2", newValue);
      }
    },
    c3: {
      get: function() {
        return this.GetValueForField("c3");
      },
      set: function(newValue) {
        this.SetValueForField("c3", newValue);
      }
    },
    c4: {
      get: function() {
        return this.GetValueForField("c4");
      },
      set: function(newValue) {
        this.SetValueForField("c4", newValue);
      }
    },
    c5: {
      get: function() {
        return this.GetValueForField("c5");
      },
      set: function(newValue) {
        this.SetValueForField("c5", newValue);
      }
    },
    c6: {
      get: function() {
        return this.GetValueForField("c6");
      },
      set: function(newValue) {
        this.SetValueForField("c6", newValue);
      }
    },
    c7: {
      get: function() {
        return this.GetValueForField("c7");
      },
      set: function(newValue) {
        this.SetValueForField("c7", newValue);
      }
    },
    c8: {
      get: function() {
        return this.GetValueForField("c8");
      },
      set: function(newValue) {
        this.SetValueForField("c8", newValue);
      }
    },
    c9: {
      get: function() {
        return this.GetValueForField("c9");
      },
      set: function(newValue) {
        this.SetValueForField("c9", newValue);
      }
    },
    c10: {
      get: function() {
        return this.GetValueForField("c10");
      },
      set: function(newValue) {
        this.SetValueForField("c10", newValue);
      }
    },
    c11: {
      get: function() {
        return this.GetValueForField("c11");
      },
      set: function(newValue) {
        this.SetValueForField("c11", newValue);
      }
    },
    c12: {
      get: function() {
        return this.GetValueForField("c12");
      },
      set: function(newValue) {
        this.SetValueForField("c12", newValue);
      }
    },
    c13: {
      get: function() {
        return this.GetValueForField("c13");
      },
      set: function(newValue) {
        this.SetValueForField("c13", newValue);
      }
    },
    c14: {
      get: function() {
        return this.GetValueForField("c14");
      },
      set: function(newValue) {
        this.SetValueForField("c14", newValue);
      }
    },
    c15: {
      get: function() {
        return this.GetValueForField("c15");
      },
      set: function(newValue) {
        this.SetValueForField("c15", newValue);
      }
    },
    c16: {
      get: function() {
        return this.GetValueForField("c16");
      },
      set: function(newValue) {
        this.SetValueForField("c16", newValue);
      }
    }
  },
  beforeCreate() {
    //check pre-requisites exist just in case
    if (window.$gz.errorHandler.devMode()) {
      if (!window.$gz._) {
        throw "custom-fields-control: $gz._ (lodash) is required and missing";
      }
      if (!window.$gz.locale) {
        throw "custom-fields-control: $gz.locale is required and missing";
      }
    }
  },
  created() {
    if (window.$gz.errorHandler.devMode()) {
      //debugger;
      if (!this.formKey) {
        throw "custom-fields-control: formKey property is required and missing";
      }
    }
  }
};
</script>
