<template>
  <div v-if="availableCustomFields.length !== 0" class="mt-2">
    <span class="text-subtitle-1">
      {{ $ay.t("ObjectCustomFieldCustomGrid") }}
    </span>

    <div class="mt-3">
      <v-row align-center justify-left row wrap>
        <template v-for="item in availableCustomFields">
          <v-col :key="item.fld" cols="12" sm="6" lg="4" xl="3" px-2>
            <!-- DATETIME  -->
            <div v-if="item.type === 1">
              <gz-date-time-picker
                :ref="item.fld"
                v-model="_self[item.dataKey]"
                :readonly="readonly"
                :disabled="disabled"
                :label="$ay.t(item.tKey)"
                :data-cy="item.fld"
                :error-messages="form().serverErrors(parentVM, item.fld)"
                :rules="[
                  form().customFieldsCheck(
                    parentVM,
                    item,
                    _self,
                    $ay.t(item.tKey)
                  )
                ]"
              ></gz-date-time-picker>
            </div>

            <!-- DATE -->
            <div v-else-if="item.type === 2">
              <gz-date-picker
                :ref="item.fld"
                v-model="_self[item.dataKey]"
                :readonly="readonly"
                :disabled="disabled"
                :label="$ay.t(item.tKey)"
                :data-cy="item.fld"
                :error-messages="form().serverErrors(parentVM, item.fld)"
                :rules="[
                  form().customFieldsCheck(
                    parentVM,
                    item,
                    _self,
                    $ay.t(item.tKey)
                  )
                ]"
              ></gz-date-picker>
            </div>
            <!-- TIME -->
            <div v-else-if="item.type === 3">
              <gz-time-picker
                :ref="item.fld"
                v-model="_self[item.dataKey]"
                :readonly="readonly"
                :disabled="disabled"
                :label="$ay.t(item.tKey)"
                :data-cy="item.fld"
                :error-messages="form().serverErrors(parentVM, item.fld)"
                :rules="[
                  form().customFieldsCheck(
                    parentVM,
                    item,
                    _self,
                    $ay.t(item.tKey)
                  )
                ]"
              ></gz-time-picker>
            </div>
            <!-- TEXT -->
            <div v-else-if="item.type === 4">
              <v-textarea
                :ref="item.fld"
                v-model="_self[item.dataKey]"
                dense
                :readonly="readonly"
                :disabled="disabled"
                :label="$ay.t(item.tKey)"
                :data-cy="item.fld"
                :error-messages="form().serverErrors(parentVM, item.fld)"
                :rules="[
                  form().customFieldsCheck(
                    parentVM,
                    item,
                    _self,
                    $ay.t(item.tKey)
                  )
                ]"
                auto-grow
                :clearable="!readonly"
              ></v-textarea>
            </div>
            <!-- INTEGER -->
            <div v-else-if="item.type === 5">
              <v-text-field
                :ref="item.fld"
                v-model="_self[item.dataKey]"
                dense
                :readonly="readonly"
                :disabled="disabled"
                :label="$ay.t(item.tKey)"
                :data-cy="item.fld"
                :error-messages="form().serverErrors(parentVM, item.fld)"
                :rules="[
                  form().customFieldsCheck(
                    parentVM,
                    item,
                    _self,
                    $ay.t(item.tKey)
                  )
                ]"
                :clearable="!readonly"
                :counter="10"
                type="number"
                step="none"
              ></v-text-field>
            </div>
            <!-- BOOL -->
            <div v-else-if="item.type === 6">
              <v-checkbox
                :ref="item.fld"
                v-model="_self[item.dataKey]"
                dense
                :readonly="readonly"
                :disabled="disabled"
                :label="$ay.t(item.tKey)"
                :data-cy="item.fld"
                :error-messages="form().serverErrors(parentVM, item.fld)"
                :rules="[
                  form().customFieldsCheck(
                    parentVM,
                    item,
                    _self,
                    $ay.t(item.tKey)
                  )
                ]"
              ></v-checkbox>
            </div>
            <!-- DECIMAL -->
            <div v-else-if="item.type === 7">
              <gz-decimal
                :ref="item.fld"
                v-model="_self[item.dataKey]"
                :readonly="readonly"
                :disabled="disabled"
                :label="$ay.t(item.tKey)"
                :data-cy="item.fld"
                :error-messages="form().serverErrors(parentVM, item.fld)"
                :rules="[
                  form().customFieldsCheck(
                    parentVM,
                    item,
                    _self,
                    $ay.t(item.tKey)
                  )
                ]"
              ></gz-decimal>
            </div>
            <!-- CURRENCY -->
            <div v-else-if="item.type === 8">
              <gz-currency
                :ref="item.fld"
                v-model="_self[item.dataKey]"
                :readonly="readonly"
                :disabled="disabled"
                :label="$ay.t(item.tKey)"
                :data-cy="item.fld"
                :error-messages="form().serverErrors(parentVM, item.fld)"
                :rules="[
                  form().customFieldsCheck(
                    parentVM,
                    item,
                    _self,
                    $ay.t(item.tKey)
                  )
                ]"
              ></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>
export default {
  props: {
    value: {
      default: "{}",
      type: String
    },
    formKey: { type: String, default: "" }, //used to grab template from store
    keyStartWith: { type: String, default: "" }, //prefix of key names used to differentiate when more than one custom fields collection on same form (i.e. workorder, workorderitem, workoritemunit etc)
    readonly: Boolean,
    disabled: Boolean,
    parentVM: {
      default: null,
      type: Object
    }
  },
  data() {
    return {};
  },
  computed: {
    availableCustomFields() {
      //item.type only exists for custom fields so they are the ones to return
      //In addition if there is a keyStartWith then there are multiple custom field controls on same form so that's a different route to take
      const template = this.$store.state.formCustomTemplate[this.formKey];

      if (template != undefined) {
        if (this.keyStartWith != "") {
          return template.filter(
            z => z.type != undefined && z.fld.includes(this.keyStartWith)
          );
        } else {
          //single custom control form, just return the fields
          return template.filter(z => z.type != undefined);
        }
      } else {
        return [];
      }
    },
    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);
      }
    }
  },

  methods: {
    form() {
      //nothing
      return window.$gz.form;
    },
    fieldValueChanged(ref) {
      if (
        !this.parentVM.formState.loading &&
        !this.parentVM.formState.readonly
      ) {
        window.$gz.form.fieldValueChanged(this.parentVM, ref);
      }
    },
    GetValueForField: function(dataKey) {
      let cData = {};
      //get the data out of the JSON string value
      if (this.value != null) {
        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

      //case 4372
      let ctrlType = null;
      if (this.keyStartWith != "") {
        ctrlType = this.$store.state.formCustomTemplate[this.formKey].find(
          z => z.dataKey == dataKey && z.fld.includes(this.keyStartWith)
        ).type;
      } else {
        //single custom control form
        ctrlType = this.$store.state.formCustomTemplate[this.formKey].find(
          z => z.dataKey == dataKey
        ).type;
      }

      //First get current value for the data that came from the server
      let 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,
        MemorySize=14
        */
        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.util.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.util.isString(ret)) {
                ret = window.$gz.util.stringToBoolean(ret);
                break;
              }
              if (ret === 1) {
                ret = true;
                break;
              }
              if (ret === 0) {
                ret = false;
                break;
              }
            }
            break;
          case 8:
          case 7:
            if (!window.$gz.util.isNumeric(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
      //
      let cData = {};
      if (this.value != null) {
        cData = JSON.parse(this.value);
      }

      if (!window.$gz.util.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();
      }

      this.$emit("input", JSON.stringify(cData));
    }
  }
};
</script>
