/** * EntityIcon.vue - Icon generation component for contacts and entities * *
Generates icons for contacts and entities using either profile images * or
DiceBear avatars. Handles CORS image transformation and fallback * to blank
square for missing identifiers. * * Features: * - Profile image display with
CORS handling * - DiceBear avatar generation for missing images * - Fallback to
blank square for missing identifiers * - Dynamic icon sizing * - Contact object
integration * * @author Matthew Raymer */
<template>
  <!-- eslint-disable-next-line vue/no-v-html -->
  <div class="w-fit" v-html="generateIcon()"></div>
</template>

<script lang="ts">
import { createAvatar, StyleOptions } from "@dicebear/core";
import { avataaars } from "@dicebear/collection";
import { Vue, Component, Prop } from "vue-facing-decorator";
import { Contact } from "../db/tables/contacts";
import blankSquareSvg from "../assets/blank-square.svg";

/**
 * EntityIcon - Icon generation component for contacts and entities
 *
 * Generates icons using profile images or DiceBear avatars with
 * proper CORS handling and fallback mechanisms.
 */
@Component({ name: "EntityIcon" })
export default class EntityIcon extends Vue {
  /** Contact object containing profile information */
  @Prop()
  contact?: Contact;

  /** Entity identifier (overridden by contact.did or profileImageUrl) */
  @Prop({ default: "" })
  entityId!: string;

  /** Icon size in pixels */
  @Prop({ default: 0 })
  iconSize!: number;

  /** Profile image URL (overridden by contact.profileImageUrl) */
  @Prop({ default: "" })
  profileImageUrl!: string;

  /**
   * Generate icon HTML based on available data
   *
   * Priority order:
   * 1. Contact profile image URL
   * 2. Direct profile image URL
   * 3. DiceBear avatar using contact DID or entity ID
   * 4. Blank square SVG as final fallback
   *
   * @returns HTML string for the icon
   */
  generateIcon(): string {
    // Check for profile image URL (highest priority)
    const imageUrl = this.contact?.profileImageUrl || this.profileImageUrl;
    if (imageUrl) {
      return `<img src="${imageUrl}" class="rounded" width="${this.iconSize}" height="${this.iconSize}" />`;
    }

    // Check for identifier for avatar generation
    const identifier = this.contact?.did || this.entityId;
    if (!identifier) {
      // Final fallback: blank square
      return `<img src="${blankSquareSvg}" class="rounded" width="${this.iconSize}" height="${this.iconSize}" />`;
    }

    // https://api.dicebear.com/8.x/avataaars/svg?seed=
    // ... does not render things with the same seed as this library.
    // "did:ethr:0x222BB77E6Ff3774d34c751f3c1260866357B677b" yields a girl with flowers in her hair and a lightning earring
    // ... which looks similar to '' at the dicebear site but which is different.
    const options: StyleOptions<object> = {
      seed: (identifier as string) || "",
      size: this.iconSize,
    };
    const avatar = createAvatar(avataaars, options);
    const svgString = avatar.toString();
    return svgString;
  }
}
</script>

<style scoped>
/* Component-specific styles if needed */
</style>
