<template>
  <q-form class="q-gutter-y-md" @submit="submit">
    <div v-if="readonly" class="q-gutter-y-sm">
      <div class="row">
        <div class="col text-grey-5">
          {{ $t('notifications.assigned') }}
        </div>
        <div class="col text-grey-7">
          <div v-for="tick in ticked" :key="`ticked-${tick}`">
            {{ tick }}
          </div>
        </div>
      </div>
    </div>
    <div v-else class="q-gutter-b-md">
      <div class="q-b-md q-px-md row q-col-gutter-sm">
        <q-tree
          class="col-12 col-sm-6"
          :nodes="rolesFormatted"
          node-key="id"
          tick-strategy="leaf"
          :ticked.sync="activeRolesIds"
          default-expand-all
        />
        <div class="col-12 col-sm-6 q-gutter-sm">
          <div class="text-h6">
            {{ $t('notifications.assigned') }}
          </div>
          <div>
            <div v-for="(tick, i) in ticked" :key="`ticked-${tick}-${i}`">
              {{ tick }}
            </div>
          </div>
        </div>
      </div>
      <div class="q-mt-md row q-gutter-y-md">
        <q-btn
          class="col-xs-12 col-sm-auto"
          color="primary"
          :label="$t('base.actions.cancel')"
          type="button"
          outline
          @click="cancelProcess"
        />
        <q-btn
          color="primary"
          class="col-xs-12 col-sm-auto q-ml-sm-md"
          :label="$t('base.send')"
          type="submit"
        />
      </div>
    </div>
  </q-form>
</template>

<script lang="ts">
import { Component, Prop, Watch } from 'vue-property-decorator';
import Vue from 'vue';
import InputData from '@/types/wf/InputData';
import { Role } from '@openapi/idm';

export declare interface QTree {
  label: string;
  disabled?: boolean;
  children?: Array<QTree>;
}

declare interface FormInputData extends InputData {
  allRoles: Array<any>;
  roles: Array<any>;
  organizationRoles: Array<any>;
}

declare interface IQTree extends QTree {
  id: string;
}

declare interface OutputData {
  rolesToAttach?: Array<string>;
  rolesToDetach?: Array<string>;
  transExit: boolean;
}

@Component({})
export default class NotificationRolesForms extends Vue {
  @Prop() readonly inputData: FormInputData;

  @Prop() readonly readonly: boolean;

  private roles: Array<Role> = [];

  private rolesFormatted: Array<IQTree> = [];

  private rolesList: Array<Role> = [];

  private activeRolesIds: Array<string> = [];

  @Watch('inputData', { immediate: true })
  private inputDataUpdate(val: FormInputData) {
    if (val) {
      this.roles = val.allRoles;
      this.rolesFormatted = this.changeProperties(val.allRoles);
      this.rolesList = val.roles ?? [];
      this.activeRolesIds = this.rolesList.map((i: Role) => i.id);
    }
  }

  private get organizationRoles(): Array<Role> {
    return this?.inputData?.organizationRoles || [];
  }

  private get ticked(): Array<string> {
    const flat = this.rolesFormatted.flatMap((e: any) => {
      return e.children.concat(e);
    });
    return (
      this.activeRolesIds.map((e: string) => {
        const found = flat.find((f: Role) => f.id === e);
        return (found && found.label) || '';
      }) || []
    );
  }

  submit(e: any): void {
    this.$emit('submit', e, this.outputData);
  }

  cancelProcess(e: any): void {
    this.$emit('submit', e, { transExit: true });
  }

  private get outputData(): OutputData {
    return {
      rolesToAttach: this.activeRolesIds.filter(
        (roleId: any) => !this.rolesList.map((i: any) => i.id).includes(roleId)
      ),
      rolesToDetach: this.rolesList
        .map((i: any) => i.id)
        .filter((roleId: any) => !this.activeRolesIds.includes(roleId)),
      transExit: false,
    };
  }

  changeProperties(arr: any): Array<IQTree> {
    if (arr && arr instanceof Array) {
      const changeList = (item: any) => {
        const returnObj = {
          id: item.id,
          label: item.name,
          disabled: this.organizationRoles.some(
            (role: any) => role.id === item.id
          ),
          ...item,
        };

        if (item.roles && item.roles instanceof Array) {
          returnObj.children = item.roles.map(changeList);
        }
        return returnObj;
      };
      return arr.filter((item) => item.roles).map(changeList);
    }
    return [];
  }
}
</script>
