import { html, nothing, TemplateResult } from 'lit';
import { property } from 'lit/decorators.js';
import { ApiDefinitions } from '@api-client/core/build/browser.js';
import { ApiDocumentationBase } from './ApiDocumentationBase.js';
import { Events } from '../../events/amf/Events.js';
import '../../define/amf/api-schema-document.js';

export default class ApiPayloadDocument extends ApiDocumentationBase {
  protected payloadValue: ApiDefinitions.IApiPayload | undefined

  @property({ type: Object })
  get payload(): ApiDefinitions.IApiPayload | undefined {
    return this.payloadValue;
  }

  set payload(value) {
    const old = this.payloadValue;
    if (old === value) {
      return;
    }
    this.payloadValue = value;
    this.processGraph();
  }

  /**
   * Queries the graph store for the API Payload data.
   */
  override async processGraph(): Promise<void> {
    await this.queryPayload();
    await this.processPayload();
    this.requestUpdate();
    await this.updateComplete;
  }

  /**
   * Queries the store for the payload data, when needed.
   * @returns {Promise<void>}
   */
  async queryPayload(): Promise<void> {
    const { domainId } = this;
    if (!domainId) {
      // this[requestValue] = undefined;
      return;
    }
    if (this.payloadValue && this.payloadValue.id === domainId) {
      // in case the request model was provided via the property setter.
      return;
    }
    try {
      const info = await Events.Payload.get(this, domainId);
      this.payloadValue = info;
    } catch (e) {
      this.payloadValue = undefined;
      const ex = e as Error;
      Events.Telemetry.exception(this, ex.message, false);
      Events.Reporting.error(this, ex, `Unable to query for API payload data: ${ex.message}`, this.localName);
    }
  }

  async processPayload(): Promise<void> {
    this.examplesValue = undefined;
    const { payload } = this;
    if (!payload) {
      return;
    }
    const { mediaType = '' } = payload;
    const { examples } = payload;
    if (Array.isArray(examples) && examples.length) {
      this.examplesValue = this.evaluateExamples(examples, mediaType);
    }
  }

  override render(): TemplateResult {
    const { payload } = this;
    if (!payload) {
      return html``;
    }
    return html`
    ${this.renderName(payload)}
    ${this.renderMediaType(payload)}
    ${this.examplesTemplate()}
    ${this.renderSchema(payload)}
    `;
  }

  /**
   * @returns The template for the payload mime type.
   */
  protected renderMediaType(payload: ApiDefinitions.IApiPayload): TemplateResult | typeof nothing {
    const { mediaType } = payload;
    if (!mediaType) {
      return nothing;
    }
    return html`
    <div class="media-type">
      <label>Media type:</label>
      <span>${mediaType}</span>
    </div>
    `;
  }

  /**
   * @returns The template for the payload name
   */
  protected renderName(payload: ApiDefinitions.IApiPayload): TemplateResult | typeof nothing {
    const { name } = payload;
    if (!name) {
      return nothing;
    }
    return html`
    <div class="payload-name text-selectable">${name}</div>
    `;
  }

  /**
   * @returns The template for the payload's schema
   */
  protected renderSchema(payload: ApiDefinitions.IApiPayload): TemplateResult {
    const { schema, mediaType } = payload;
    if (!schema) {
      return html`<div class="empty-info">Schema is not defined for this payload.</div>`;
    }
    return html`
    <api-schema-document class="schema-renderer" .schema="${schema}" .mimeType="${mediaType}" forceExamples schemaTitle></api-schema-document>
    `;
  }
}
