<template>
  <v-card flat elevation="0">
    <v-card-title v-if="title">{{ title }}</v-card-title>
    <v-card-subtitle v-if="subtitle">{{ subtitle }}</v-card-subtitle>
    <v-card-text>
      <v-form>

<!-- Sample text -->

        <dougal-fixed-string-encoder-sample
          :label="label"
          :hint="hint"
          :properties="properties"
          :fields="fields"
          :values.sync="values"
        ></dougal-fixed-string-encoder-sample>

<!-- Fields -->

        <v-container>

          <v-row no-gutters class="mb-2">
            <h4>Fields</h4>
          </v-row>

          <dougal-fixed-string-encoder-field v-for="(field, key) in fields" :key="key"
            v-model="fields[key]"
            :properties="properties"
            :colour="getHSLColourFor(field.item)"
            :readonly="readonly"
          >
            <template v-slot:append v-if="editableFieldList && !readonly">
              <v-btn
                class="ml-3"
                fab
                text
                small
                title="Remove this field"
              >
                <v-icon
                  color="error"
                  @click="removeField(key)"
                >mdi-minus</v-icon>
              </v-btn>
            </template>
          </dougal-fixed-string-encoder-field>

          <v-row no-gutters class="mb-2" v-if="editableFieldList && !readonly">
            <h4>Add new field</h4>
          </v-row>

          <dougal-fixed-string-encoder-field v-if="editableFieldList && !readonly"
            v-model="newField"
            :properties="properties"
            :colour="getHSLColourFor(newField.item)"
          >
            <template v-slot:prepend>
              <v-btn v-if="isFieldDirty(newField)"
                top
                text
                small
                title="Reset"
              >
                <v-icon
                  color="warning"
                  @click="resetField(newField)"
                >mdi-backspace-reverse-outline</v-icon>
              </v-btn>
            </template>
            <template v-slot:append>
              <v-btn
                class="ml-3"
                fab
                text
                small
                title="Add field"
                :disabled="isFieldValid(newField) !== true"
              >
                <v-icon
                  color="primary"
                  @click="addField(newField)"
                >mdi-plus</v-icon>
              </v-btn>
            </template>
          </dougal-fixed-string-encoder-field>

        </v-container>



      </v-form>
    </v-card-text>
    <v-card-actions>
    </v-card-actions>
  </v-card>
</template>

<style scoped>

.input {
  flex: 1 1 auto;
  line-height: 20px;
  padding: 8px 0 8px;
  min-height: 32px;
  max-height: 32px;
  max-width: 100%;
  min-width: 0px;
  width: 100%;
}

.input, .multiline >>> .chunk-field {
  padding-inline: 1px;
  border: 1px solid;
}

.input, .multiline >>> .chunk-fixed {
  padding-inline: 1px;
  border: 1px dashed;
}

.input, .multiline >>> .chunk-empty {
  padding-inline: 1px;
}

.input, .multiline >>> .chunk-overlap {
  padding-inline: 1px;
  border: 1px solid grey;
  color: grey;
}

.input >>> .chunk-mismatch {
  padding-inline: 1px;
  border: 2px solid red !important;
}
</style>

<script>
import { getHSLColourFor } from '@/lib/hsl'
import DougalFixedStringEncoderField from './fixed-string-encoder-field'
import DougalFixedStringEncoderSample from './fixed-string-encoder-sample'

export default {
  name: "DougalFixedStringEncoder",

  components: {
    DougalFixedStringEncoderField,
    DougalFixedStringEncoderSample
  },

  mixins: [
    {
      methods: {
        getHSLColourFor
      }
    }
  ],

  props: {
    properties: { type: Object },
    fields: { type: Array },
    values: { type: Object },
    editableFieldList: { type: Boolean, default: true },
    readonly: Boolean,
    title: String,
    subtitle: String,
    label: String,
    hint: String,
  },

  data () {
    return {
      //< The reason for not using this.text directly is that at some point
      //< we might extend this component to allow editing the sample text.
      text_: "",
      //< The value of a fixed string that should be always present at a specific position
      fixedName: "",
      fixedOffset: 0,
      //< The name of a new field to add.
      fieldName: "",
      newField: {
        item: null,
        when: null,
        offset: null,
        length: null,
        value: null,
        pad_side: null,
        pad_string: null
      }
    }
  },

  computed: {

    chunks () {
      const properties = this.properties;
      const fields = this.fields;
      const values = this.values;
      const str = "";
      const chunks = [];

      for (const field of fields) {

        //console.log("FIELD", structuredClone(field));
        //console.log("VALUES DATA", values[field.item]);
        let value;

        if (field.item == "text") {
          value = field.value;
        } else if (properties[field.item]?.type == "boolean") {
          if (values[field.item] === field.when) {
            value = field.value;
          }
        } else {
          value = values[field.item];
        }

        if (value != null) {

          value = String(value);
          if (field.pad_side == "left") {
            value = value.padStart(field.length, field.pad_string);
          } else {
            value = value.padEnd(field.length, field.pad_string);
          }

          const chunk = {
            start: field.offset,
            end: field.offset + field.length - 1,
            colour: this.getHSLColourFor(field.item),
            class: field.item == "text" ? "fixed" : "field",
            text: value
          }

          //console.log("CHUNK", chunk);
          chunks.push(chunk);

        }

      }

      return chunks;
    },

    html () {
      return this.renderTextLine(this.sample(this.properties, this.fields, this.values));
      //return this.sample(this.properties, this.fields, this.values);
    }

  },

  watch: {
  },

  methods: {

    isFieldDirty (field) {
      return Object.entries(field).reduce( (acc, cur) => cur[1] === null ? acc : true, false );
    },

    isFieldValid (field) {
      if (!field.item) return "Missing item";
      if (typeof field.offset !== "number" || field.offset < 0) return "Missing offset";
      if (typeof field.length !== "number" || field.length < 1) return "Missing length";
      if (!this.properties[field.item]) return "Unrecognised property";
      if (this.properties[field.item].type == "text" && !field.value?.length) return "Missing value";
      if (this.properties[field.item].type == "boolean" && !field.value?.length) return "Missing value (boolean)";
      if(!!field.pad_side && !field.pad_string) return "Missing pad string";

      return true;
    },

    resetField (field) {
      field.item = null;
      field.when = null;
      field.offset = null;
      field.length = null;
      field.value = null;
      field.pad_side = null;
      field.pad_string = null;

      return field;
    },

    addField (field) {
      if (this.isFieldValid(field)) {
        const fields = structuredClone(this.fields);
        fields.push({...field});
        this.resetField(field);
        console.log("update:fields", fields);
        this.$emit("update:fields", fields);
      }
    },

    removeField (key) {
      console.log("REMOVE", "update:fields", key, this.fields);
      const fields = structuredClone(this.fields);
      fields.splice(key, 1);
      this.$emit("update:fields", fields);
    },

  },

  mounted () {
  }

}
</script>
