<template>
  <ExampleStory>
    <TfFormList
      v-model="model"
      v-bind="{
        ...tfFormListProps,
        rules,
      }"
      @added="onEmit('added', $event)"
      @blur="onEmit('blur', $event)"
      @deleted="onEmit('deleted', $event)"
      @input="onEmit('input', $event)"
      @update:disabledOptions="onEmit('update:disabledOptions', $event)"
      @update:formListOptions="onEmit('update:formListOptions', $event)"
    >
      <template #label="{ index }">
        <template v-if="!index">
          This is the first form item (slot)
        </template>
      </template>

      <template #error="{ error }">
        <!-- This is just a dumb example of how to use the "error" data. -->
        <span v-if="error.includes('customerror')">
          display errors with custom markup (including <a
            href="https://www.google.com"
            target="_blank"
          >links</a>) by passing them into a scoped slot.
          slot name is "error" and will provide scoped "error" prop<br>
          { error: {{ error }} }<br>
        </span>
      </template>
    </TfFormList>
    <template #controls>
      <div>
        <h3>model:</h3>
        <pre>{{ model }}</pre>
      </div>
      <div>
        <ElForm label-position="top">
          <h3>Props</h3>
          <template v-for="prop in Object.keys(options).sort()">
            <ElFormItem
              v-if="options[prop].controller"
              :key="prop"
              size="medium"
            >
              <template #label>
                {{ prop }}
                <TfTooltip
                  v-if="options[prop].description"
                  :options="{
                    placement: 'top-start',
                  }"
                  class="description-help"
                >
                  <p>{{ options[prop].description }}</p>
                  <icon
                    slot="reference"
                    name="question-circle"
                  />
                </TfTooltip>
              </template>
              <ElSwitch
                v-if="options[prop].controller === 'switch'"
                v-model="options[prop].value"
              />
              <ElCheckboxGroup
                v-else-if="options[prop].controller === 'checkbox'"
                v-model="options[prop].value"
              >
                <TfCheckbox
                  v-for="option in options[prop].options"
                  :key="option"
                  :label="option"
                />
              </ElCheckboxGroup>
              <ElInput
                v-if="options[prop].controller === 'string'"
                v-model="options[prop].value"
              />
            </ElFormItem>
          </template>
        </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';

  export default {
    name: 'ExampleFormList',
    components: { ExampleStory },
    data: () => ({
      disabledOptions: [],
      emits: [],
      formListOptions: [],
      model: [],
      options: {
        allowAddAnother: {
          controller: 'switch',
          value: true,
        },
        allowAddInline: {
          controller: 'switch',
          value: false,
        },
        allowDuplicates: {
          controller: 'switch',
          value: false,
        },
        allowDeleteFirst: {
          controller: 'switch',
          value: false,
          description: 'If allowDeleteFirst is true, the delete icon will display for all form items by default even if it is the very last item in the list. The hideDeleteForValues prop takes presedence, however, and can override this behavior.',

        },
        disableDeleteFirst: {
          controller: 'switch',
          value: false,
          description: 'If disableDeleteFirst is true, the delete icon will display as disabled if a form item is the very last item in the list and allowDeleteFirst is true. The hideDeleteForValues prop takes presedence, however, and can override this behavior.',

        },
        groupDisabled: {
          controller: 'switch',
          value: false,
        },
        groupedDisabledOptionsTitle: {
          controller: 'string',
          value: 'Used values',
        },
        hideDeleteForValues: {
          controller: 'checkbox',
          value: [],
          options: ['option 1', 'option 2'],
          description: 'Check one of the boxes below to hide the delete icon/ability for an input field that shares the same value. For example, check the first box below and enter it\'s text into an input field above to see this in action.',
        },
        isDisabled: {
          controller: 'switch',
          value: false,
        },
        isSingleLabel: {
          controller: 'switch',
          value: true,
        },
        label: {
          controller: 'string',
          value: 'Form list label',
        },
        optionKey: {
          value: 'value',
        },
        optionLabel: {
          value: 'label',
        },
        options: {
          value: [
            { label: 'option 1', value: 'option 1' },
            { label: 'option 2', value: 'option 2' },
            { label: 'john@acme.com', value: 'john@acme.com' },
            { label: 'option 4', value: 'option 4' },
            { label: 'option 5', value: 'option 5' },
            {
              isDisabled: true,
              label: 'option 6 is disabled by parent component',
              value: 'option 6',
            },
          ],
        },
        readonlyValues: {
          controller: 'checkbox',
          value: [],
          options: ['Taco', 'Dragon', 'Bilbo'],
          description: 'Readonly values are still deletable but can not be editted. Check one of the boxes below to enable readonly for an input field that shares the same value. For example, check the first box below and enter it\'s text into an input field above to see this in action.',
        },
        rules: {
          controller: 'checkbox',
          value: [],
          options: ['domain', 'min', 'required', 'customerror'],
          description: 'Check one of the boxes below to select a rule to validate the input value against. By default, error messages are strings. Checking "customerror" will activate the scoped error slot in the Element TfFormItem and display the custom markup passed into it.',

        },
        placeholder: {
          controller: 'string',
          value: 'custom placeholder text',
        },
        showUsedAsDisabled: {
          controller: 'switch',
          value: false,
        },
        value: {
          value: [],
        },
      },
    }),
    computed: {
      /**
       * Reduce the options down to the props consumed by tfFormList.
       *
       * @returns {object}
       */
      tfFormListProps() {
        return Object.entries(this.options).reduce((acc, [prop, { value }]) => {
          if (['rules', 'value'].includes(prop)) {
            return acc;
          }

          acc[prop] = value;

          return acc;
        }, {});
      },
      /**
       * Custom rules for examples.
       *
       * @returns {object}
       */
      rules() {
        return this.options.rules.value.length
          ? [{
            required: this.options.rules.value.includes('required'),
            trigger: 'manual',
            validator: (rule, value, callback) => {
              const domains = ['acme.com', 'unum.com'];
              const extension = value && value.includes('@')
                ? value.split('@')[1]
                : null;

              if (!value && this.options.rules.value.includes('required')) {
                callback(new Error('Please input the value again.'));
              } else if (value) {
                if (this.options.rules.value.includes('customerror')) {
                  callback(new Error('customerror'));
                } else if (
                  this.options.rules.value.includes('domain')
                  && !domains.includes(extension)
                ) {
                  callback(new Error(`Contacts must end in @${domains.join(', @')}.`));
                } else if (
                  this.options.rules.value.includes('min')
                  && value.length < 3
                ) {
                  callback(new Error('At least 3 characters are required.'));
                } else {
                  callback();
                }
              }
            },
          }]
          : [];
      },
    },
    methods: {
      /**
       * 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';

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

  .el-checkbox + .el-checkbox {
    margin-left: 0;
  }

  ::v-deep .tf-tooltip {
    width: 250px;
  }
</style>
