<script lang="ts">
  import { i18n } from "../i18n";
  import EntitySetEditor from "./EntitySetEditor.svelte";
  import EntryView from "./EntryView.svelte";
  import Icon from "./utils/Icon.svelte";
  import EntityList from "./widgets/EntityList.svelte";
  import api from "../lib/api";
  import { Query } from "@upnd/upend";
  import { ATTR_IN } from "@upnd/upend/constants";
  import { createEventDispatcher } from "svelte";
  const dispatch = createEventDispatcher();

  export let spec: string;

  const individualSpecs = spec.split(/(?=[+=-])/);
  let includedGroups = individualSpecs
    .filter((s) => s.startsWith("+"))
    .map((s) => s.slice(1));
  let requiredGroups = individualSpecs
    .filter((s) => s.startsWith("="))
    .map((s) => s.slice(1));
  let excludedGroups = individualSpecs
    .filter((s) => s.startsWith("-"))
    .map((s) => s.slice(1));

  $: if (
    includedGroups.length === 0 &&
    requiredGroups.length === 0 &&
    excludedGroups.length === 0
  ) {
    dispatch("close");
  }

  const combinedWidgets = [
    {
      name: "List",
      icon: "list-check",
      components: ({ entities }) => [
        {
          component: EntityList,
          props: {
            entities,
            thumbnails: false,
          },
        },
      ],
    },
    {
      name: "EntityList",
      icon: "image",
      components: ({ entities }) => [
        {
          component: EntityList,
          props: {
            entities,
            thumbnails: true,
          },
        },
      ],
    },
  ];

  let resultEntities = [];
  async function updateResultEntities(
    includedGroups: string[],
    requiredGroups: string[],
    excludedGroups: string[],
  ) {
    const included = includedGroups.length
      ? (
          await api.query(
            new Query().matches(
              undefined,
              ATTR_IN,
              includedGroups.map((g) => `@${g}`),
            ),
          )
        ).objects
      : [];
    const required = requiredGroups.length
      ? (
          await api.query(
            new Query().matches(
              undefined,
              ATTR_IN,
              requiredGroups.map((g) => `@${g}`),
            ),
          )
        ).objects
      : [];
    const excluded = excludedGroups.length
      ? (
          await api.query(
            new Query().matches(
              undefined,
              ATTR_IN,
              excludedGroups.map((g) => `@${g}`),
            ),
          )
        ).objects
      : [];
    resultEntities = Object.keys(included)
      .filter((e) => !requiredGroups.length || Object.keys(required).includes(e))
      .filter((e) => !Object.keys(excluded).includes(e));
  }
  $: updateResultEntities(includedGroups, requiredGroups, excludedGroups);
</script>

<div class="view" data-address-multi={resultEntities}>
  <h2>
    <Icon plain name="intersect" />
    {$i18n.t("Combine")}
  </h2>
  <div class="controls">
    <EntitySetEditor
      entities={includedGroups}
      header={$i18n.t("Include")}
      confirmRemoveMessage={null}
      on:add={(ev) => (includedGroups = [...includedGroups, ev.detail])}
      on:remove={(ev) =>
        (includedGroups = includedGroups.filter((e) => e !== ev.detail))}
    />
    <EntitySetEditor
      entities={requiredGroups}
      header={$i18n.t("Require")}
      confirmRemoveMessage={null}
      on:add={(ev) => (requiredGroups = [...requiredGroups, ev.detail])}
      on:remove={(ev) =>
        (requiredGroups = requiredGroups.filter((e) => e !== ev.detail))}
    />
    <EntitySetEditor
      entities={excludedGroups}
      header={$i18n.t("Exclude")}
      confirmRemoveMessage={null}
      on:add={(ev) => (excludedGroups = [...excludedGroups, ev.detail])}
      on:remove={(ev) =>
        (excludedGroups = excludedGroups.filter((e) => e !== ev.detail))}
    />
  </div>
  <div class="entities">
    <EntryView
      title={$i18n.t("Matching entities")}
      entities={resultEntities}
      widgets={combinedWidgets}
    />
  </div>
</div>

<style lang="scss">
  .view {
    display: flex;
    flex-direction: column;
    height: 100%;
  }

  h2 {
    text-align: center;
    margin: 0;
    margin-top: -0.66em;
  }

  .controls {
    margin-bottom: 1rem;
  }

  .entities {
    flex-grow: 1;
    overflow-y: auto;
    height: 0;
  }
</style>
