import { __decorate } from "tslib";
import { html } from 'lit';
import { property, state } from 'lit/decorators.js';
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
import { ifDefined } from 'lit/directives/if-defined.js';
import { AmfNamespace } from '@api-client/core/build/browser.js';
import { ApiDocumentationBase } from './ApiDocumentationBase.js';
import { sanitizeHTML } from '../../amf/lib/Utils.js';
import * as UrlLib from '../../amf/lib/UrlUtils.js';
import { NavigationEvents } from '../../events/amf/NavigationEvents.js';
import { ApiEvents } from '../../events/amf/ApiEvents.js';
import { ReportingEvents } from '../../events/amf/ReportingEvents.js';
import { TelemetryEvents } from '../../events/amf/TelemetryEvents.js';
import { ServerEvents } from '../../events/amf/ServerEvents.js';
import { EndpointEvents } from '../../events/amf/EndpointEvents.js';
import '../../define/highlight/marked-highlight.js';
/**
 * A web component that renders the documentation page for an API documentation (like in RAML documentations) built from
 * the AMF graph model.
 */
export default class ApiSummary extends ApiDocumentationBase {
    get summary() {
        return this.summaryValue;
    }
    get servers() {
        return this.serversValue;
    }
    get endpoints() {
        if (this.endpointsValue) {
            return [...this.endpointsValue];
        }
        return undefined;
    }
    constructor() {
        super();
        this.titleLevel = 2;
    }
    connectedCallback() {
        super.connectedCallback();
        this.processDebounce();
    }
    /**
     * Queries the graph store for the API data.
     */
    async processGraph() {
        await this.querySummary();
        await this.queryServers();
        await this.queryEndpoints();
        await this.processSummary();
        this.requestUpdate();
    }
    /**
     * Queries the API store for the API summary object.
     */
    async querySummary() {
        this.summaryValue = undefined;
        try {
            const info = await ApiEvents.summary(this);
            this.summaryValue = info;
        }
        catch (e) {
            const ex = e;
            TelemetryEvents.exception(this, ex.message, false);
            ReportingEvents.error(this, ex, `Unable to query for API summary data: ${ex.message}`, this.localName);
        }
    }
    /**
     * Queries the API store for the API summary object.
     */
    async queryServers() {
        this.serversValue = undefined;
        try {
            const info = await ServerEvents.query(this);
            this.serversValue = info;
        }
        catch (e) {
            const ex = e;
            TelemetryEvents.exception(this, ex.message, false);
            ReportingEvents.error(this, ex, `Unable to query for API servers: ${ex.message}`, this.localName);
        }
    }
    /**
     * Logic executed after the summary is requested from the store.
     */
    async processSummary() {
        this.isAsyncValue = undefined;
        const { summary } = this;
        if (!summary) {
            return;
        }
        this.isAsyncValue = summary.types.includes(AmfNamespace.aml.vocabularies.apiContract.AsyncAPI);
    }
    /**
     * Queries the API endpoints and methods.
     */
    async queryEndpoints() {
        this.endpointsValue = undefined;
        try {
            const info = await EndpointEvents.list(this);
            this.endpointsValue = info;
        }
        catch (e) {
            const ex = e;
            TelemetryEvents.exception(this, ex.message, false);
            ReportingEvents.error(this, ex, `Unable to query for API endpoints: ${ex.message}`, this.localName);
        }
    }
    navigateHandler(e) {
        e.preventDefault();
        const target = e.composedPath()[0];
        const data = target.dataset;
        if (!data.id || !data.shapeType) {
            return;
        }
        NavigationEvents.apiNavigate(this, data.id, data.shapeType, data.parent);
    }
    render() {
        const { summary } = this;
        if (!summary) {
            return html ``;
        }
        return html `
    ${this.titleTemplate()}
    ${this.versionTemplate()}
    ${this.descriptionTemplate(summary.description)}
    ${this.serversTemplate()}
    ${this.protocolsTemplate()}
    ${this.contactInfoTemplate()}
    ${this.licenseTemplate()}
    ${this.termsOfServiceTemplate()}
    ${this.endpointsTemplate()}
    `;
    }
    titleTemplate() {
        const { summary, titleLevel } = this;
        if (!summary || !summary.name) {
            return '';
        }
        return html `
    <div class="api-title" role="heading" aria-level="${titleLevel || ''}" part="api-title">
      <label part="api-title-label">API title:</label>
      <span class="text-selectable">${summary.name}</span>
    </div>`;
    }
    versionTemplate() {
        const { summary } = this;
        if (!summary || !summary.version) {
            return '';
        }
        return html `
    <p class="inline-description version" part="api-version">
      <label>Version:</label>
      <span class="text-selectable">${summary.version}</span>
    </p>`;
    }
    /**
     * @returns A template for a server, servers, or no servers
     * whether it's defined in the main API definition or not.
     */
    serversTemplate() {
        const { servers, baseUri } = this;
        if (baseUri) {
            return this.baseUriTemplate(undefined);
        }
        if (!servers || !servers.length) {
            return '';
        }
        if (servers.length === 1) {
            return this.baseUriTemplate(servers[0]);
        }
        return html `
    <div class="servers" slot="markdown-html">
      <p class="servers-label">API servers</p>
      <ul class="server-lists">
        ${servers.map((server) => this.serverTemplate(server))}
      </ul>
    </div>`;
    }
    /**
     * @param server Server definition
     * @returns A template for a single server in the main API definition
     */
    baseUriTemplate(server) {
        const { baseUri, protocols } = this;
        const uri = UrlLib.computeApiBaseUri({ baseUri, server, protocols, });
        return html `
    <div class="endpoint-url">
      <div class="url-value">${uri}</div>
    </div>
    `;
    }
    /**
     * @param server Server definition
     * @returns Template for a server list items when there is more than one server.
     */
    serverTemplate(server) {
        const { baseUri, protocols } = this;
        const uri = UrlLib.computeApiBaseUri({ baseUri, server, protocols, });
        const { description } = server;
        return html `
    <li class="text-selectable">
      ${uri}
      ${description ? html `<marked-highlight .markdown=${description} class="server-description"></marked-highlight>` : ''}
    </li>`;
    }
    protocolsTemplate() {
        const { summary } = this;
        if (!summary || !summary.schemes || !summary.schemes.length) {
            return '';
        }
        const result = summary.schemes.map((item) => html `<span class="chip text-selectable">${item}</span>`);
        return html `
    <label class="section">Supported protocols</label>
    <div class="protocol-chips">${result}</div>`;
    }
    contactInfoTemplate() {
        const { summary } = this;
        if (!summary || !summary.provider || !summary.provider.name) {
            return '';
        }
        const { name = '', email, url } = summary.provider;
        const link = url ? sanitizeHTML(`<a href="${url}" target="_blank" class="app-link provider-url text-selectable">${url}</a>`) : '';
        return html `
    <section role="contentinfo" class="docs-section" part="info-section">
      <label class="section">Contact information</label>
      <p class="inline-description" part="info-inline-desc">
        <span class="provider-name text-selectable">${name}</span>
        ${email ? html `<a class="app-link link-padding provider-email text-selectable" href="mailto:${email}">${email}</a>` : ''}
      </p>
      ${url ? html ` <p class="inline-description text-selectable" part="info-inline-desc">${unsafeHTML(link)}</p>` : ''}
    </section>`;
    }
    licenseTemplate() {
        const { summary } = this;
        if (!summary || !summary.license) {
            return '';
        }
        const { url, name } = summary.license;
        if (!url || !name) {
            return '';
        }
        const link = sanitizeHTML(`<a href="${url}" target="_blank" class="app-link text-selectable">${name}</a>`);
        return html `
    <section aria-labelledby="licenseLabel" class="docs-section" part="license-section">
      <label class="section" id="licenseLabel">License</label>
      <p class="inline-description">
        ${unsafeHTML(link)}
      </p>
    </section>`;
    }
    termsOfServiceTemplate() {
        const { summary } = this;
        if (!summary || !summary.termsOfService || !summary.termsOfService.length) {
            return '';
        }
        return html `
    <section aria-labelledby="tocLabel" class="docs-section">
      <label class="section" id="tocLabel">Terms of service</label>
      <marked-highlight .markdown="${summary.termsOfService}" sanitize>
        <div slot="markdown-html" class="markdown-body text-selectable"></div>
      </marked-highlight>
    </section>`;
    }
    endpointsTemplate() {
        if (this.hideToc) {
            return '';
        }
        const endpoints = this.endpointsValue;
        if (!endpoints || !endpoints.length) {
            return '';
        }
        const result = endpoints.map((item) => this.endpointTemplate(item));
        const pathLabel = this.isAsyncValue ? 'channels' : 'endpoints';
        return html `
    <div class="separator" part="separator"></div>
    <div class="toc" part="toc">
      <label class="section endpoints-title">API ${pathLabel}</label>
      ${result}
    </div>
    `;
    }
    endpointTemplate(item) {
        const { operations = [] } = item;
        const ops = operations.length ? operations.map((op) => this.methodTemplate(op, item)) : '';
        return html `
    <div class="endpoint-item" @click="${this.navigateHandler}" @keydown="${() => { }}">
      ${item.name ? this.endpointNameTemplate(item) : this.endpointPathTemplate(item)}
      <div class="endpoint-header">
        ${ops}
      </div>
    </div>`;
    }
    endpointPathTemplate(item) {
        return html `
    <a
      class="endpoint-path text-selectable"
      href="#${item.path}"
      data-id="${ifDefined(item.id)}"
      data-shape-type="resource"
      title="Open endpoint documentation">${item.path}</a>
    `;
    }
    endpointNameTemplate(item) {
        if (!item.name) {
            return '';
        }
        return html `
    <a
      class="endpoint-path text-selectable"
      href="#${item.path}"
      data-id="${ifDefined(item.id)}"
      data-shape-type="resource"
      title="Open endpoint documentation">${item.name}</a>
    <p class="endpoint-path-name">${item.path}</p>
    `;
    }
    methodTemplate(item, endpoint) {
        return html `
      <a
        href="#${`${endpoint.path}/${item.method}`}"
        class="http-label pill"
        data-method="${item.method}"
        data-id="${item.id}"
        data-shape-type="operation"
        data-parent="${ifDefined(endpoint.id)}"
        title="Open method documentation">${item.method}</a>
    `;
    }
}
__decorate([
    property({ type: String })
], ApiSummary.prototype, "baseUri", void 0);
__decorate([
    property({ type: Number })
], ApiSummary.prototype, "titleLevel", void 0);
__decorate([
    property({ type: Boolean })
], ApiSummary.prototype, "hideToc", void 0);
__decorate([
    state()
], ApiSummary.prototype, "protocols", void 0);
//# sourceMappingURL=ApiSummary.element.js.map