<template>
  <widget-wrapper v-bind="$props" v-show="!isHidden" ref="widget">
    <base-label-value v-if="inlineTable" :padded-label="paddedGroups">
      <template v-slot:label>
        {{ fieldNode.label ? fieldNode.label : '' }}
      </template>
      <template v-slot:value>
        <q-table
          v-bind="props"
          class="no-shadow text-grey-9 card-table"
          wrap-cells
          hide-bottom
          table-header-class="text-primary card-table__header"
          :columns="columns"
          :data="values"
          :rows-per-page-options="[0]"
        >
          <template v-slot:body-cell="props">
            <q-td :props="props">
              <reference-book-item
                v-if="
                  get(props.col, 'listAttr.props.dictionary') && props.value
                "
                :dictionary="props.col.listAttr.props.dictionary"
                :value="props.value"
              />
              <template v-else>
                {{ props.value }}
              </template>
            </q-td>
          </template>
        </q-table>
      </template>
    </base-label-value>
    <q-table
      v-else
      :title="fieldNode.label"
      class="no-shadow text-grey-9 card-table"
      :title-class="
        'q-pa-none card-table__title ' + (paddedGroups ? 'q-pl-md' : '')
      "
      :table-class="paddedGroups ? 'q-pl-md' : ''"
      wrap-cells
      hide-bottom
      :grid="grid"
      :columns="columns"
      :data="values"
      :rows-per-page-options="[0]"
      v-bind="props"
    >
      <template #header="props">
        <q-tr :props="props">
          <q-th
            v-for="col in props.cols"
            :key="col.name"
            :props="props"
            class="no-wrap"
          >
            {{ col.label }}
          </q-th>
          <q-th></q-th>
        </q-tr>
      </template>
      <template v-slot:body="props">
        <q-tr :props="props" class="relative-position">
          <q-td v-for="col in props.cols" :key="col.name">
            <DictionarySelectForComponents
              v-if="get(col, 'listAttr.props.dictionary')"
              :dictionary="col.listAttr.props.dictionary"
              :is-readonly="isReadonly"
              :option-value="col.listAttr.props.optionValue"
              v-model="props.row[col.name]"
            />
            <template v-else>
              <div class="flex items-center">
                <span
                  style="white-space: pre"
                  v-if="get(col, 'listAttr.props.preFormatted')"
                >
                  {{ col.value }}
                </span>
                <span v-else>
                  {{ col.value }}
                </span>
                <template v-if="!isReadonly && get(col, 'listAttr.editable')">
                  <q-btn
                    v-if="
                      !hideEditControlForNotEmptyValue ||
                      isEmpty(props.row[col.name])
                    "
                    class="on-right cursor-pointer"
                    icon="edit"
                    dense
                    text-color="blue-grey-8"
                    size="xs"
                  />
                  <q-popup-edit v-model="props.row[col.name]" auto-save>
                    <q-input
                      autofocus
                      v-if="get(col, 'listAttr.type') === 'string'"
                      v-model="props.row[col.name]"
                      dense
                      outlined
                    ></q-input>
                    <arm-datepicker
                      v-if="get(col, 'listAttr.type') === 'date'"
                      autofocus
                      ref="armDatepicker"
                      :type="get(col, 'listAttr.type')"
                      v-bind="get(col, 'listAttr.props')"
                      :value="props.row[col.name]"
                      :noLabels="true"
                      :label="''"
                      @input="$set(props.row, col.name, $event)"
                    />
                  </q-popup-edit>
                </template>
              </div>
            </template>
          </q-td>
          <q-td class="absolute">
            <q-btn
              v-if="!isReadonly"
              v-show="values.length > 1"
              class="q-mt-xs"
              icon="delete"
              @click="removeTableRow(props.rowIndex)"
            />
          </q-td>
        </q-tr>
      </template>

      <template v-slot:item="props">
        <q-separator
          v-show="props.rowIndex > 0"
          :class="{ 'q-ml-md': paddedGroups }"
        />
        <template v-for="col in props.cols">
          <div
            class="full-width q-my-sm"
            v-show="
              typeof col.value === 'number' ||
              col.value ||
              !hideOnFalsyDefaultTrue
            "
            :key="col.name + props.rowIndex"
          >
            <base-label-value :padded-label="!!fieldNode.label">
              <template v-slot:label>
                <div :class="{ 'q-pl-md': paddedGroups }">
                  {{ col.label ? col.label : '' }}
                </div>
              </template>
              <template v-slot:value>
                <reference-book-item
                  v-if="get(col, 'listAttr.props.dictionary') && col.value"
                  :dictionary="col.listAttr.props.dictionary"
                  :value="col.value"
                />
                <template
                  v-else-if="
                    col.listAttr.type === 'boolean' && col.value !== ''
                  "
                >
                  {{ getBooleanAsString(col.value) }}
                </template>
                <template v-else>
                  {{ col.value }}
                </template>
              </template>
            </base-label-value>
          </div>
        </template>
      </template>

      <template
        v-slot:bottom-row="props"
        v-if="!isReadonly && !hideCreateButton"
      >
        <q-tr no-hover>
          <q-td :colspan="columns.length" class="text-center center">
            <q-btn icon="add" @click="addTableRow">Добавить строку</q-btn>
          </q-td>
        </q-tr>
      </template>
      <template v-slot:no-data v-if="!isReadonly && !hideCreateButton">
        <q-tr no-hover>
          <q-td :colspan="columns.length" class="text-center center">
            <q-btn icon="add" @click="addTableRow">Добавить строку</q-btn>
          </q-td>
        </q-tr>
      </template>
    </q-table>
  </widget-wrapper>
</template>

<script lang="ts">
import { Component, Prop, Ref } from 'vue-property-decorator';
import {
  ValidatedField,
  FormWidget,
  FormGeneratorDateType,
  WidgetWrapper,
} from '@devsun/form-generator/dist';
import type WidgetWrapperClass from '@devsun/form-generator/dist/WidgetWrapper';
import { Schema, Model } from '@devsun/eva-models';
import get from 'lodash/get';
import isEmpty from 'lodash/isEmpty';
import ArmDatepicker from '../datepicker/arm-datepicker.vue';
import DictionarySelectForComponents from '@/components/common/dictionary-select/index.vue';
import { mixins } from 'vue-class-component';
import { QTableColumn } from '@/models/models-ui';

@Component({
  components: {
    DictionarySelectForComponents,
    WidgetWrapper,
    ArmDatepicker,
  },
  methods: {
    get,
    isEmpty,
  },
})
export default class CardTable extends mixins(FormWidget, ValidatedField) {
  @Prop({ default: FormGeneratorDateType.none })
  type: FormGeneratorDateType;

  protected get props(): any {
    return this.fieldNode?.rawAttrs?.props || undefined;
  }

  @Ref('widget') widgetRef!: WidgetWrapperClass;

  @Prop({}) paddedGroups!: boolean;
  @Prop({}) hideNulls!: boolean;
  @Prop({ default: false }) hideCreateButton!: boolean;
  @Prop({ default: false }) hideEditControlForNotEmptyValue!: boolean;
  @Prop() hideOnFalsy?: boolean;
  @Prop({ default: false }) isDense!: boolean;

  get hideOnFalsyDefaultTrue(): boolean {
    const { props } = this;
    return !props || !('hideOnFalsy' in props) || !!this.hideOnFalsy;
  }

  get values(): any[] {
    const value = this.value && this.value.__id;
    return Array.isArray(value) ? value : value ? [value] : [];
  }

  get isHidden(): boolean {
    return this.hideNulls && !this.values.length;
  }

  get grid(): boolean {
    return this.mode === 'grid';
  }

  get inlineTable(): boolean {
    return this.mode === 'inline-table';
  }

  get mode(): 'table' | 'inline-table' | 'grid' {
    return get(this, 'fieldNode.reference.mode', 'inline-table');
  }

  get columns(): QTableColumn[] {
    return get(this, 'fieldNode.reference.listAttrs', [])
      .filter((listAttr: Schema.ListedAttr) => !listAttr.hidden)
      .map((listAttr: Schema.ListedAttr) => ({
        align: 'left',
        field: (row: Model.Base) => get(row, listAttr.name, ''),
        label: listAttr.label,
        name: listAttr.name,
        listAttr,
        sortable: true,
        classes: 'text-primary',
      }));
  }

  get isReadonly(): boolean {
    if (this.fieldNode.simlink) {
      return true;
    }

    return Boolean(this.fieldNode.readonly);
  }

  get fieldClasses() {
    return {
      editable: !this.fieldNode.readonly,
      'label-uppercase': false,
      dense: this.isDense,
    };
  }

  getBooleanAsString(val: boolean): string {
    return val === true ? 'Да' : 'Нет';
  }

  addTableRow(): void {
    let item: Record<string, string> = {};

    for (let col of this.columns) {
      item[col.name] = '';
    }

    if (this.value.__id === '' && this.value.content === '') {
      this.widgetRef.inputEvents?.input([]);
      this.$nextTick(() => {
        this.value.__id.push(item);
      });
    } else {
      this.value.__id.push(item);
    }
  }

  removeTableRow(index: number): void {
    this.value.__id.splice(index, 1);
  }
}
</script>

<style scoped lang="sass">
.card-table::v-deep
  th:first-child, td:first-child
    padding-left: 0

  th:last-child, td:last-child
    padding-right: 0

  .q-table__top
    padding: 0

  .q-table__grid-content
    display: block

  .card-table__title
    font-size: inherit

  .card-table__header > th
    padding-top: 0
    font-size: inherit
    vertical-align: top
</style>
