<script>
import { oidcClientComputed } from '../../state/modules/oidc-client';
import { utilsAppMethods } from '../../state/modules/utils/app';
import Mustache from 'mustache';
import uniq from 'lodash/uniq';
import flatMap from 'lodash/flatMap';
import every from 'lodash/every';
import XMultiPartlet from './components/XMultiPartlet';
import { USER_SCOPES } from '../../constants/entities/Scope';
import { notifyError } from '../../utils/notify';
import sub from 'date-fns/sub';
import format from 'date-fns/format';

const today = new Date();
const dateFormat = 'dd.MM.yyyy';
const timeFormat = 'HH:mm:ss';
const config = [
  // Получено заявлений
  {
    id: 'a6e0fad5-04f3-49b6-bd85-0e2b8cc56e78',
    hint: `не ранее, чем за ${ format(sub(today, { months: 1 }), `${dateFormat} ${timeFormat}`) }`
  },
  // В обработке заявлений
  {
    id: '09f2e29f-bda2-4a1c-a9e1-2fc870977c78',
    hint: `по состоянию на ${ format(today, `${dateFormat}`) }`
  }
];

export default {
  components: {
    XMultiPartlet,
  },
  data() {
    return {
      pagination: {
        page: 1,
        rowsPerPage: this.getItemsPerPage(),
      },
      columns: [
        { name: 'src', label: 'Src', field: 'src' },
        { name: 'title', label: 'Title', field: 'title' },
        { name: 'type', label: 'Type', field: 'type' },
      ],
      loading: false,
      data: [],
      gridAreas: [],
      playWithMe: {
        dialog: false,
        json: '',
      },
    };
  },
  computed: {
    ...oidcClientComputed,
    cardContainerClass() {
      if (this.$q.screen.gt.xs) {
        return (
          'grid-masonry grid-masonry--' + (this.$q.screen.gt.sm ? '3' : '2')
        );
      }

      return void 0;
    },

    grid() {
      const sizesOrder = ['xs', 'sm', 'md', 'lg', 'xl'];
      let gridAreas;

      // получаем раскладку для текущего или меньшего экрана
      for (let i = sizesOrder.indexOf(this.$q.screen.name); i >= 0; i--) {
        if (sizesOrder[i] in this.gridAreas) {
          gridAreas = this.gridAreas[sizesOrder[i]];
          break;
        }
      }

      let max = 0;
      const areas =
        gridAreas &&
        gridAreas
          .map((el) => {
            max = Math.max(el.match(/\S+/g).length, max);
            return `"${el}"`;
          })
          .join(' ');

      return `grid-template-areas: ${areas};grid-template-columns: repeat(${max}, 1fr)`;
    },

    rowsPerPageOptions() {
      if (this.$q.screen.gt.xs) {
        return this.$q.screen.gt.sm ? [3, 6, 9] : [3, 6];
      }

      return [3];
    },
  },

  watch: {
    '$q.screen.name'() {
      this.pagination.rowsPerPage = this.getItemsPerPage();
    },
  },

  created() {
    this.initCards();
  },

  methods: {
    ...utilsAppMethods,
    getItemsPerPage() {
      const { screen } = this.$q;
      if (screen.lt.sm) {
        return 6;
      }
      if (screen.lt.md) {
        return 6;
      }
      return 10;
    },
    _setCards(json) {
      // делаем плоский xs если нет
      if (!json.grid.xs) {
        for (const key in json.grid) {
          json.grid.xs = uniq(
            flatMap(json.grid[key], (el) => el.match(/\S+/g))
          );
        }
      }

      this.gridAreas = json.grid;

      const enrichedData = json.cards.map(c => {
        const card = config.find(cardConfig => c.src.includes(cardConfig.id));
        if (card) {
          return { ...c, hint: card.hint }
        } else {
          return c;
        }
      });

      this.data = enrichedData;
    },
    /*
              Проверка условия для типа партлета iframe-condition
              Сделано на коленке, в будущем надо подыскать какю-то либу
              или вообще не попадать в такие ситуации.)

              Условие приходит в виде
              {
                <ключ>[.[!]<метод>]: <значение>
              }
              Например:
              {
                scope.!includes: 'Admin' // scope не должен содержать админа
              }

              Возвращает 1 или 0 (как индексы массива переданных урлов в src)
             */
    compareCondition(condition) {
      // todo усложнить (а может и не надо?..)
      const allowedMethods = ['includes'];
      return +every(condition, (value, key, method) => {
        [key, method] = key.split('.');
        let xor = 0;

        if (!method) return this.currentUser[key] === value;

        if (method.startsWith('!')) {
          method = method.slice(1);
          xor = 1;
        }

        if (!allowedMethods.includes(method)) return false;

        return this.currentUser[key][method](value) ^ xor;
      });
    },
    async initCards() {
      this.loading = true;
      let name = 'app.config.registrar.json';

      const configurationMap = {
        'app.config.registrar.json': [USER_SCOPES.REGISTRAR],
        'app.config.signedSpecialist.json': [USER_SCOPES.SIGNED_SPECIALIST],
        'app.config.specialist.json': [USER_SCOPES.SPECIALIST],
        'app.config.organizationAdmin.json': [USER_SCOPES.ORGANIZATION_ADMIN],
      };

      for (const [key, value] of Object.entries(configurationMap)) {
        if (this.$AC.haveOneOfScope(value)) {
          name = key;
          break;
        }
      }
      this.getResource(name);
    },
    getResource(name) {
      this.fetchResource({
        name,
      })
        .then(async (response) => {
          const json = JSON.parse(response).dashboard;

          this._setCards(json);

          this.playWithMe.json = JSON.stringify(json, null, 4);
          this.loading = false;
        })
        .catch((e) => {
          notifyError(e.message.toString());
          this.loading = false;
        });
      window.setTimeout(() => {
        if (this.loading) {
          notifyError(this.$t('dashboard.pending'));
          this.loading = false;
        }
      }, 20000);
    },
    playWithMeHandler() {
      this.playWithMe.dialog = true;
    },
    playWithMeOkHandler() {
      const json = JSON.parse(this.playWithMe.json);

      this._setCards(json);

      this.playWithMe.dialog = false;
    },
    render(val) {
      if (Array.isArray(val)) return val.map(this.render);
      val = val.replace(
        /^https?:\/\/platform\.apps\.dev?\.devsun\.ru/,
        location.origin
      );
      return Mustache.render(val, this.currentUser);
    },
  },
};
</script>

<template>
  <q-page class="q-pa-sm">
    <!--<div class="text-right q-px-sm">
            <q-btn
                    @click="playWithMeHandler"
                    label="Настройки"
            />
        </div>-->
    <q-dialog v-model="playWithMe.dialog">
      <q-card class="no-shadow">
        <q-card-section>
          <div class="text-h6">JSON</div>
        </q-card-section>
        <q-card-section>
          <textarea
            v-model="playWithMe.json"
            class="full-height"
            style="min-height: 200px; min-width: 400px"
          />
        </q-card-section>
        <q-card-actions align="right">
          <q-btn label="Ok" @click="playWithMeOkHandler" />
        </q-card-actions>
      </q-card>
    </q-dialog>
    <q-table
      v-if="data.length"
      grid
      card-container-class="grid"
      :card-container-style="grid"
      class="grid-table"
      :data="data"
      :columns="columns"
      row-key="name"
      hide-header
      :pagination.sync="pagination"
      :rows-per-page-options="rowsPerPageOptions"
    >
      <template #item="props">
        <div class="q-pa-sm" :style="`grid-area: ${props.row.name};`">
          <q-card class="full-height column no-shadow" :style="props.row.style">
            <div v-if="props.row.title">
              <q-card-section class="text-center">
                {{ props.row.title }}
              </q-card-section>
              <q-separator inset />
            </div>
            <q-card-section class="col relative-position aspect-ratio--16x9">
              <vue-friendly-iframe
                v-if="props.row.type === 'iframe'"
                class="iframe"
                class-name="iframe"
                :src="render(props.row.src)"
              />
              <x-multi-partlet
                v-else-if="props.row.type === 'x-multi-partlet'"
                class="iframe"
                :src="render(props.row.src)"
                :options="props.row.options"
              />
              <vue-friendly-iframe
                v-else-if="props.row.type === 'iframe-condition'"
                class="iframe"
                class-name="iframe"
                :src="
                  render(props.row.src[compareCondition(props.row.condition)])
                "
              />
              <div
                v-if="props.row.hint"
                class="absolute-top-right row items-center justify-center"
                style="width: 30px; height: 30px;"
              >
                <q-icon name="help" flat size="20px" color="blue-grey-3" />
                <q-tooltip>
                  {{ props.row.hint }}
                </q-tooltip>
              </div>
            </q-card-section>
          </q-card>
        </div>
      </template>
    </q-table>
    <q-inner-loading :showing="loading">
      <q-spinner-gears color="primary" size="50px" />
    </q-inner-loading>
  </q-page>
</template>

<style lang="sass">
.aspect-ratio--16x9
    padding-bottom: 46.25%
    & .iframe
        position: absolute
        top: 0
        bottom: 0
        left: 0px
        right: 0

.grid
    display: grid

    &-table
        .q-table__middle
            display: none

.iframe
    display: block
    height: 100%
    width: 100%
</style>
