<template>
<div>
  <div v-if="formTittle" class="page-title">
    <h1>{{formTittle}}</h1>
  </div> 
  <section class="block">
    <div class="row">
        <div class="col-12">
          <div class="col-12 p-5" v-show="showError||showSuccess">
            <appup-alert :message="messageAlert" alertType="failure" :show="showError" @dismissed="showError=false"></appup-alert>
            <appup-alert :message="messageAlert" alertType="success" :show="showSuccess" @dismissed="showSuccess=false"></appup-alert>
          </div>                
          <b-form
              :id=id
              class="appup-form"
              @submit="onSubmit"
              @reset="onReset"
              novalidate>
              <div class="mb-2" :class="{'d-none': position!='top',
                                          'text-center': direction=='center',
                                          'text-left': direction=='left',
                                          'text-right': direction=='right' }">
                  <b-button class="submit-button" v-for="(btn, index) in buttons" :key="`btn-top-${index}`" :type="btn.type" :variant="btn.variant">{{btn.label}}</b-button>
                  <br>
              </div>
              <template v-for="(item, n) in formFields">
                  <b-form-group :id="'fgroup_'+item.id"
                      :label="item.label"
                      :label-for="'input_'+item.id"
                      :key="n">
                      <!-- <appup-input v-if="!item.component ||item.component == 'appup-input'"
                          :id="'input_'+item.id"
                          :disabled=item.disabled
                          :name="item.name"
                          :options="item.option"
                          v-model="form[item.name]"
                          :type="item.type"
                          :placeholder="item.placeholder"
                          :url="item.url ? item.url : null"
                          v-validate="fetchValidationRules(item)"
                          :state="errors.has(item.name) ? false : null"
                          :supportedFormats="item.supportedFormats ? item.supportedFormats : null"
                          @input="onInput"
                          @dynamicAddInput="dynamicAddInput"
                      /> -->
                      <!-- Date Component -->
            <template  v-if=" item.type == 'date'|| item.type == 'time'|| item.type == 'datetime'|| item.type == 'daterange'">
                <appup-datetime
                    :id="'input_'+item.id"
                    v-model="form[item.name]"
                    @input="onInput"
                    v-validate="fetchValidationRules(item)"
                    :state="errors.has(item.name) ? false : null"
                    :type="item.type"/>
            </template>

            <!-- Hidden Component -->
            <template v-else-if="item.type == 'hidden'">
                <appup-hidden/>
            </template>

            <!-- Textarea Component -->
            <template v-else-if="item.type == 'textarea'">
                <appup-textarea
                    :id="'input_'+item.id"
                    v-model="form[item.name]"
                    @input="onInput"
                    v-validate="fetchValidationRules(item)"
                    :placeholder="item.placeholder"
                    :state="errors.has(item.name) ? false : null"
                />
            </template>

            <!-- Editor Component -->
            <template v-else-if="item.type == 'editor'">
                <appup-editor
                    :id="'input_'+item.id"
                    v-model="form[item.name]"
                    @input="onInput"
                    v-validate="fetchValidationRules(item)"
                    :placeholder="item.placeholder"
                    :state="errors.has(item.name) ? false : null"
                />
            </template>

            <!-- Radio Component -->
            <template v-else-if="item.type == 'radio'">
                <appup-radio
                    :id="'input_'+item.id"
                    :addElement=addElement
                    :options="item.option"
                    v-model="form[item.name]"
                    v-validate="fetchValidationRules(item)"
                    @input="onInput"
                    :state="errors.has(item.name) ? false : null"
                    @radioChange="dynamicAddInput"
                    />
            </template>

            <!-- Checkbox Component -->
            <template v-else-if="item.type == 'checkbox'">
                <appup-checkbox
                    :id="'input_'+item.id"
                    :addElement=addElement
                    :options="item.option"
                    v-model="form[item.name]"
                    v-validate="fetchValidationRules(item)"
                    @input="onInput"
                    @checkboxChange="dynamicAddInput"
                    :state="errors.has(item.name) ? false : null"
                />
            </template>

            <!-- Dropdown Component -->
            <template v-else-if="item.type == 'dropdown'">
                <appup-dropdown
                    :id="'input_'+item.id"
                    :url="item.url ? item.url : null"
                    :addElement=addElement
                    :options="item.option"
                    v-model.lazy="form[item.name]"
                    v-validate="fetchValidationRules(item)"
                    @input="onInput"
                    :state="errors.has(item.name) ? false : null"
                    @dropdownChange="dynamicAddInput"
                    />
            </template>

            <!-- Multiselect Component -->
            <template v-else-if="item.type == 'multiselect'">
                <appup-multiselect
                    :id="'input_'+item.id"
                    :options="item.option"
                    v-model="form[item.name]"
                    v-validate="fetchValidationRules(item)"
                    @input="onInput"
                    :state="errors.has(item.name) ? false : null"
                    :url="item.url ? item.url : null"
                    />
            </template>

            <!-- Tags Component -->
            <template v-else-if="item.type == 'tags'">
                <appup-tags
                    :id="'input_'+item.id"
                    :options="item.option"
                    v-model="form[item.name]"
                    v-validate="fetchValidationRules(item)"
                    @input="onInput"
                    :state="errors.has(item.name) ? false : null"
                    :url="item.url ? item.url : null"
                    />
            </template>

            <!-- File Component -->
            <template v-else-if="item.type == 'file'">
                <appup-file
                  :id="'input_'+item.id"
                    v-model="form[item.name]"
                    v-validate="fetchValidationRules(item)"
                    @input="onInput"
                    :state="errors.has(item.name) ? false : null"
                    :placeholder="item.placeholder"
                    :supportedFormats="item.supportedFormats ? item.supportedFormats : null"
                    />
            </template>
          
            <!-- Text Input Component -->
            <template v-else-if="item.type == 'text'||'email'||'number'">
                <b-form-input
                    :disabled=item.disabled
                    class="appup-input"
                    :id="'input_'+item.id"
                    :name="item.name"
                    :type="item.type"
                    :placeholder="item.placeholder"
                    v-model="form[item.name]"
                    v-validate="fetchValidationRules(item)"
                    @input="onInput"
                    :state="errors.has(item.name) ? false : null">
                </b-form-input>
            </template>
                        <component :name="item.component" v-else :is="item.component" v-bind="item.option" v-validate="fetchValidationRules(item)">
                            <div>You are seeing this message in window which is displayed center of the screen</div>
                            <div v-for="(item, index) in item.option.items" :key="index" :slot="item.id">
                                <appup-form v-bind="item.content"/>
                            </div>
                        </component>
                        <span v-show="errors.has(item.name)" class="invalid-feedback" style="display: block">{{ errors.first(item.name) }}</span>
                    </b-form-group>
                </template>
                <div class="mb-2" :class="{'d-none': position!='bottom',
                                            'text-center': direction=='center',
                                            'text-left': direction=='left',
                                            'text-right': direction=='right'}">
                    <b-button class="submit-button" v-for="(btn, index) in buttons" :key="`btn-bottom-${index}`" :type="btn.type" :variant="btn.variant"
                    @click="onCustomClick(btn.function, $event, btn)">{{btn.label}}</b-button>
                </div>
                <pre class="d-none">{{ inputs }}</pre>
          </b-form>
        </div>      
      </div>
  </section>
</div>
</template>

<script>
/**
 * Appup Form component rendering form elements based upon provided schema. Includes validation rules as well.
 *
 * TODOs:
 *
 * Reset form elements
 *
 * Submit form data to API
 *
 * Testing edit with form data prepopulated
 *
 * Dynamic element added based on other component selection
 */
import { AjaxRequests } from "@/mixins/ajaxRequests";
import { Workflow } from "@/mixins/workflow";
import Dropdown from "@/components/inputs/dropdown";

export default {
  name: "appup-form",
  mixins: [AjaxRequests, Workflow],
  props: {
    /**
     * Id of input elements.
     */
    id: {
      type: String,
      required: false
    },

    /**
     * Position of group buttons.
     *
     * `top`, `bottom`
     */
    position: {
      type: String,
      required: false,
      default: "bottom"
    },

    /**
     * Position of group buttons.
     *
     * `center`, `left`, `right`
     */
    direction: {
      type: String,
      required: false,
      default: "left"
    },

    /**
     * URL to deserialize the form initially.
     */
    preload: {
      type: String,
      required: false
    },

    /**
     * Submit Workflow ID
     */
    submit: {
      type: String,
      required: false
    },
    /**
     * Name of input elements.
     */
    name: {
      type: String,
      required: false
    },

    /**
     * Fetch data with url
     */
    url: {
      type: String,
      required: false
    },

    /**
     * The type attribute specifies the type of <strong>input</strong> element to display.
     *
     * <var>text, password, email, number,url, tel</var>
     * <br/><var>date, time, datetime, daterange</var>
     * <br/><var>radio, checkbox, textarea, hidden, code, editor</var>
     * <br/><var>dropdown, multiselect, tags</var>
     *
     */
    type: {
      type: String,
      required: false,
      default: "text"
    },

    /**
     * The placeholder attribute specifies a short hint that describes the expected value of an input field.
     */
    placeholder: {
      type: String,
      required: false
    },

    /**
     * Model Object that should be passed to the input
     */
    value: {
      required: false
    },

    /**
     * Options for Dropdown, Radio & Checkbox
     */
    options: {
      type: Array,
      required: false
    },

    /**
     * State of the input field based upon validation rules
     *
     * false - highlights the field in red
     * <br/>true - highlights the field in green
     * <br/>null - nothing
     */
    state: {
      type: Boolean,
      required: false,
      default: null
    },

    /**
     * Url from which data should be populated in the input field
     *
     * Applicable for appup-dropdown, appup-multiselect, appup-tags
     */
    url: {
      type: String,
      required: false
    },

    /**
     * Supported extension files to be selected when input type is File
     *
     * Example: ['.jpg', '.pdf', '.docx'] etc..
     */
    supportedFormats: {
      type: Array,
      required: false
    },

    /**
     * @ignore
     */
    disabled: {
      type: Boolean,
      required: false
    },

    /**
     * Flag to check type of add element or valid the value.
     *
     * `true, false`
     */
    addElement: {
      type: Boolean,
      required: false,
      default: false
    },
    /**
     * form tittle
     */
    formTittle: {
      type: String,
      required: false
    }
  },
  data: function() {
    return {
      form: {},
      typeAlert: "failure",
      showSuccess: false,
      showError: false,
      messageAlert: "",
      inputValue: this.value,
      formFields: [],
      buttons: []
    };
  },
  watch: {
    value(newVal, oldVal) {
      this.inputValue = newVal;
    },
    formFields(newVal, oldVal) {
      this.formFields.forEach(field => {
        if(field.value)
        this.form[field.name] = field.value.toString()
          ? field.type == "text" ? field.value.toString() : field.value
          : "";
      });
    }
  },
  created() {
    this.formFields.forEach(field => {
      if (field.value) {
        this.form[field.name] = field.value.toString()
          ? field.type == "text" ? field.value.toString() : field.value
          : "";
      }
    });

    if (this.preload) this.start(this.preload);
  },
  methods: {
    onSubmit(evt) {
      evt.preventDefault();

      // Call the workflow
      if (this.submit) {
        console.log("Calling workflow");
        this.start(this.submit);
      }
    },
    onReset(evt) {
      evt.preventDefault();
      this.errors.clear();
    },
    onCancel(evt) {
      console.log("cancel");
      evt.preventDefault();
    },
    onSuccess(evt, success, response) {
      console.log("response", response);
      switch (success.type) {
        case "navigate":
          this.onNavigate(evt, success.data);
          break;
      }
      evt.preventDefault();
    },
    onError(evt, error) {
      switch (error.type) {
        case "navigate":
          this.onNavigate(evt, error.data);
          break;
      }
      evt.preventDefault();
    },
    onInput(e) {
      // console.log("---> on input : "+e, this.errors, this.form);
    },
    fetchValidationRules(field) {
      let rule = {};

      // Set Required
      if (field.required) {
        rule.required = field.required;
      }

      // Validation rules based upon field type
      if (
        field.type == "text" ||
        field.type == "password" ||
        field.type == "textarea" ||
        field.type == "editor"
      ) {
        if (field.minLength) {
          rule.min = field.minLength;
        }
        if (field.maxLength) {
          rule.max = field.maxLength;
        }
      } else if (field.type == "email") {
        rule.email = true;
      } else if (field.type == "number") {
        rule.numeric = true;
        if (field.min) {
          rule.min_value = field.min;
        }
        if (field.max) {
          rule.max_value = field.max;
        }
      }
      return rule;
    },
    wait(ms, cb) {
      setTimeout(cb, ms);
    },
    dynamicAddInput(arr, id, type) {
      console.log(arr, id, type);
      for (let i = 0; i < this.formFields.length; i++) {
        if (
          this.formFields[i].id.toString().split("-")[3] === "added" &&
          this.formFields[i].id.split("-")[1] === type
        ) {
          this.formFields.splice(i, 1);
          i--;
        }
      }
      let isArray = true;
      if (!Array.isArray(arr)) {
        arr = [arr];
        isArray = false;
      }
      setTimeout(() => {
        for (let i = 0; i < this.formFields.length; i++) {
          if (this.formFields[i].id.toString() === id.split("_")[1]) {
            arr.forEach(child => {
              let e = Object.assign({}, child);
              e.name = type + "-" + e.value + "-added";
              e.id = id + "-" + type + "-" + e.value + "-added";
              this.form[e.name + "_" + e.id] = "";
              this.formFields.splice(i + 1, 0, e);
            });
            return;
          }
        }
      }, 0);
    },
    onInput(value) {
      console.log("==> input value :: ", value);
      this.$emit("input", value);
    },
    dynamicAddInput(value, id, type) {
      this.$emit("dynamicAddInput", value, id, type);
    },
    showAlertError(error) {
      console.log(error);
      this.showError = true;
      this.messageAlert = error.data.responseText;
    },
    showAlertSuccess(error, transfer) {
      console.log(error, transfer);
      this.showSuccess = true;
      this.messageAlert = error.data;
    }
  }
};
</script>