<template>
  <ExampleStory>
    <TfFormBuilder
      id="example-form-builder"
      v-bind="{
        formItems: exampleFormItems,
        isLoaded: true,
      }"
      v-model="exampleFormModel"
      @blur="onEmit('blur', $event)"
      @input="onEmit('input', $event)"
      @submit="onEmit('submit', $event)"
      @switchChange="onEmit('switchChange', $event)"
    >
      <template #label="{ prop }">
        <template v-if="prop === 'commissions'">
          #label for {{ prop }}
        </template>
      </template>
      <template #formElement="{ formItem }">
        <ElInput
          v-if="formItem.props.prop === 'date'"
          v-bind="{
            disabled: true,
            placeholder: 'disabled on purpose',
            type: formItem.type,
            value: exampleFormItems[formItem.props.prop],
          }"
        />
      </template>
    </TfFormBuilder>
    <template #controls>
      <div>
        <h3>model:</h3>
        <pre>{{ exampleFormModel }}</pre>
      </div>
      <div>
        <ElForm label-position="top">
          <h3>Add Form elements</h3>
          <div
            v-for="(model, modelIndex) in newFormModel"
            :key="modelIndex"
            class="new-element-container"
          >
            <TfFormBuilder
              v-model="newFormModel[modelIndex]"
              v-bind="{
                formItems: newFormItems,
                isLoaded: true,
              }"
            >
              <template #formElement="{ formItem }">
                <ElInput
                  v-if="formItem.props.prop === 'width'"
                  v-model="newFormModel[modelIndex].width"
                  type="number"
                >
                  <template #append>
                    %
                  </template>
                </ElInput>
              </template>
            </TfFormBuilder>
          </div>
          <div class="btn-group">
            <TfButton
              class="btn-add-column"
              icon="plus"
              size="text"
              type="primary"
              @click="addColumn"
            >
              Add another column
            </TfButton>

            <TfButton
              :disabled="btnAddIsDisabled"
              class="btn-add-elements"
              icon="plus"
              size="medium"
              type="primary"
              @click="addFormItem"
            >
              Add element{{ newFormModel.length === 1 ? '' : '(s)' }}
            </TfButton>
          </div>
        </ElForm>
      </div>
      <div>
        <h3>@emits:</h3>
        <div
          v-for="({ name, payload }, index) in emits"
          :key="index"
          class="emit"
        >
          <h4>name: {{ name }}</h4>
          <pre>{{ payload }}</pre>
        </div>
      </div>
    </template>
  </ExampleStory>
</template>

<script>
  import ExampleStory from '@/views/examples/Layouts/Story';

  const elementTypes = [
    'switch',
    'text',
    'date',
    'textarea',
    'select',
  ];
  const newModel = {
    label: 'new label',
    required: true,
    type: '',
    width: null,
  };
  const options = ['option a', 'option 2', 'option 3'].map((value) => ({ label: value, value }));

  export default {
    name: 'ExampleFormBuilder',
    components: { ExampleStory },
    data: () => ({
      exampleFormItems: [
        [{
          props: {
            label: '#formElement slot',
            placeholder: 'gibberish',
            prop: 'date',
            type: 'date',
          },
        }],
        [{
          props: {
            label: 'Commission level',
            placeholder: 'Select commission level',
            prop: 'commissions',
            options,
            optionKey: 'value',
            optionLabel: 'label',
            type: 'select',
          },
          rules: {
            message: 'Commission level is required.',
            trigger: 'manual',
            required: true,
          },
        }],
      ],
      exampleFormModel: {
        date: null,
        commissions: null,
      },
      newFormItems: [
        [
          {
            props: {
              label: 'New element type',
              placeholder: 'Select an element',
              options: elementTypes.map((type) => ({
                label: type, value: type,
              })),
              prop: 'type',
              optionKey: 'value',
              optionLabel: 'label',
              type: 'select',
            },
            rules: {
              required: true,
              trigger: 'manual',
              validator: (rule, value, callback) => {
                if (!value || !elementTypes.includes(value)) {
                  callback(new Error(`Element must be ${elementTypes.join(', ')}.`));
                } else {
                  callback();
                }
              },
            },
          },
          {
            props: {
              label: 'Required',
              prop: 'required',
              type: 'switch',
            },
          },
        ],
        [
          {
            props: {
              label: 'Label',
              prop: 'label',
              type: 'text',
            },
          },
          {
            props: {
              label: 'Width',
              prop: 'width',
              type: 'number',
            },
          },
        ],
        [
          {
            props: {
              label: 'Tooltip (select type only)',
              prop: 'tooltip',
              type: 'text',
            },
          },
        ],
      ],
      newFormModel: [{ ...newModel }],
      emits: [],
    }),
    computed: {
      /**
       * Evaluate all the models in the new form for any that don't include the correct type.
       *
       * @returns {boolean}
       */
      btnAddIsDisabled() {
        return this.newFormModel.some(({ type }) => !elementTypes.includes(type));
      },
    },
    methods: {
      /**
       * Add an empty form for a new form element.
       */
      addColumn() {
        this.newFormModel.push({ ...newModel });
      },
      /**
       * Create new form items to feed into the example model based on the newFormModel.
       */
      addFormItem() {
        const newElements = [];

        this.newFormModel.forEach(({
          label,
          required,
          type,
          width,
          tooltip,
        }) => {
          const id = (Math.floor(Math.random() * Math.floor(9999)).toString());
          const newElement = {
            props: {
              label,
              prop: id,
              type,
            },
            rules: {
              message: `${label} is required.`,
              required,
              trigger: 'manual',
            },
            width: width ? `${width}%` : null,
          };

          if (type === 'date') {
            newElement.props.format = 'MM/dd/yy';
            newElement.props.placeholder = 'mm/dd/yy';
          } else if (type === 'select') {
            newElement.props.options = options;
            newElement.props.optionKey = 'value';
            newElement.props.optionLabel = 'label';
            if (tooltip) {
              newElement.props.tooltip = tooltip;
            }
          }

          this.exampleFormModel[id] = null;
          newElements.push(newElement);
        });

        this.exampleFormItems.push(newElements);
        this.$set(this, 'newFormModel', [newModel]);
      },
      /**
       * Updates the `payloads.emitted` object to the latest payload for display only purposes.
       *
       * @param {string} name
       * @param {object} payload
       */
      onEmit(name, payload) {
        this.emits.unshift({ name, payload });
      },
    },
  };
</script>

<style lang="scss" scoped>
  @import 'src/assets/styles/variables';

  .btn-group {
    margin: 20px 0;
    justify-content: space-between;
  }

  .emit {
    padding: 10px 0;
    border-bottom: 1px solid $tf-extra-light-gray-1;
  }

  .new-element-container {
    display: flex;
    flex-direction: column;

    .el-form {
      margin-bottom: 10px;
      padding: 20px 20px 0;
      background: $tf-white;
    }
  }

  #example-form-builder {
    max-width: 500px;
    min-height: 500px;
  }
</style>
