<template>
    <div class="frappe-form">
        <form-actions
          v-if="shouldRenderForm"
          :doc="doc"
          @save="save"
          @submit="submit"
          @revert="revert"
        />
        <div class="p-3">
          <form-layout
            v-if="shouldRenderForm"
            :doc="doc"
            :fields="meta.fields"
            :layout="meta.layout"
            :invalid="invalid"
          />
        </div>
        <not-found v-if="notFound" />
    </div>
</template>
<script>
import frappe from 'frappejs';
import FormLayout from './FormLayout';
import FormActions from './FormActions';
import { _ } from 'frappejs/utils';

export default {
  name: 'Form',
  props: ['doctype', 'name', 'defaultValues'],
  components: {
    FormActions,
    FormLayout
  },
  data() {
    return {
      docLoaded: false,
      notFound: false,
      invalid: false,
      invalidFields: []
    }
  },
  computed: {
    meta() {
      return frappe.getMeta(this.doctype);
    },
    shouldRenderForm() {
      return this.name && this.docLoaded;
    }
  },
  async created() {
    if (!this.name) return;
    try {
      this.doc = await frappe.getDoc(this.doctype, this.name);

      if (this.doc._notInserted && this.meta.fields.map(df => df.fieldname).includes('name')) {
        // For a user editable name field,
        // it should be unset since it is autogenerated
        this.doc.set('name', '');
      }

      if (this.defaultValues) {
        for (let fieldname in this.defaultValues) {
          const value = this.defaultValues[fieldname];
          this.doc.set(fieldname, value);
        }
      }

      this.docLoaded = true;
    } catch(e) {
      this.notFound = true;
    }
  },
  methods: {
    async save() {
      this.setValidity();
      if (this.invalid) return;

      try {
        if (this.doc._notInserted) {
          await this.doc.insert();
        } else {
          await this.doc.update();
        }

        this.$emit('save', this.doc);

      } catch (e) {
        console.error(e);
        return;
      }
    },

    async submit() {
      this.doc.set('submitted', 1);
      await this.save();
    },

    async revert() {
      this.doc.set('submitted', 0);
      await this.save();
    },

    onValidate(fieldname, isValid) {
      if (!isValid && !this.invalidFields.includes(fieldname)) {
        this.invalidFields.push(fieldname);
      } else if (isValid) {
        this.invalidFields = this.invalidFields.filter(invalidField => invalidField !== fieldname)
      }
    },

    setValidity() {
      const form = this.$el.querySelector('form');
      let validity = form.checkValidity();
      this.invalid = !validity;
    },
  }
};
</script>
<style>
</style>
