import { __decorate } from "tslib";
import { html } from 'lit';
import { property } from 'lit/decorators.js';
import { ApiDocumentationBase } from './ApiDocumentationBase.js';
import { QueryParameterProcessor } from '../../amf/lib/QueryParameterProcessor.js';
import { Events } from '../../events/amf/Events.js';
import '../../define/amf/api-payload-document.js';
import '../../define/amf/api-parameter-document.js';
import '../../define/ui/ui-radio.js';
import '../../define/ui/ui-divider.js';
/**
 * A web component that renders the documentation page for an API request object.
 */
export default class ApiRequestDocument extends ApiDocumentationBase {
    /**
     * @returns true when has cookie parameters definition
     */
    get hasCookieParameters() {
        const request = this.requestValue;
        if (!request) {
            return false;
        }
        return Array.isArray(request.cookieParameters) && !!request.cookieParameters.length;
    }
    /**
     * @returns true when has headers parameters definition
     */
    get hasHeaders() {
        const request = this.requestValue;
        if (!request) {
            return false;
        }
        return Array.isArray(request.headers) && !!request.headers.length;
    }
    /**
     * @returns true when has query parameters definition
     */
    get hasQueryParameters() {
        const request = this.requestValue;
        if (!request) {
            return false;
        }
        return Array.isArray(request.queryParameters) && !!request.queryParameters.length;
    }
    /**
     * @returns The combined list of path parameters in the server, endpoint, and the request.
     */
    get uriParameters() {
        const request = this.requestValue;
        const { server, endpoint } = this;
        let result = [];
        if (server && Array.isArray(server.variables) && server.variables.length) {
            result = result.concat(server.variables);
        }
        if (endpoint && Array.isArray(endpoint.parameters) && endpoint.parameters.length) {
            result = result.concat(endpoint.parameters);
        }
        if (request && Array.isArray(request.uriParameters) && request.uriParameters.length) {
            result = result.concat(request.uriParameters);
        }
        return result;
    }
    /**
     * @returns true when has query string definition
     */
    get hasQueryString() {
        const request = this.requestValue;
        if (!request) {
            return false;
        }
        return !!request.queryString;
    }
    get payloadValue() {
        const { mimeType } = this;
        const payloads = this.payloadsValue;
        if (!Array.isArray(payloads) || !payloads.length) {
            return undefined;
        }
        if (!mimeType) {
            return payloads[0];
        }
        return payloads.find((item) => item.mediaType === mimeType);
    }
    get request() {
        return this.requestValue;
    }
    set request(value) {
        const old = this.requestValue;
        if (old === value) {
            return;
        }
        this.requestValue = value;
        this.processGraph();
    }
    async processGraph() {
        this.mimeType = undefined;
        await this.queryRequest();
        await this.queryPayloads();
        await this.processQueryParameters();
        this.preselectMime();
        this.requestUpdate();
        await this.updateComplete;
    }
    /**
     * Queries the store for the request data, when needed.
     */
    async queryRequest() {
        const { domainId } = this;
        if (!domainId) {
            // this.requestValue = undefined;
            return;
        }
        if (this.requestValue && this.requestValue.id === domainId) {
            // in case the request model was provided via the property setter.
            return;
        }
        try {
            const info = await Events.Request.get(this, domainId);
            this.requestValue = info;
        }
        catch (e) {
            this.requestValue = undefined;
            const ex = e;
            Events.Telemetry.exception(this, ex.message, false);
            Events.Reporting.error(this, ex, `Unable to query for API request data: ${ex.message}`, this.localName);
        }
    }
    async queryPayloads() {
        const { request } = this;
        if (!request || !request.payloads.length) {
            this.payloadsValue = undefined;
            return;
        }
        this.payloadsValue = request.payloads;
    }
    /**
     * Creates a parameter
     */
    async processQueryParameters() {
        this.queryParametersValue = undefined;
        const { request } = this;
        if (!request) {
            return;
        }
        const nodeShape = request.queryString;
        if (!nodeShape) {
            return;
        }
        const factory = new QueryParameterProcessor();
        const params = factory.collectOperationParameters(request.queryString, 'query');
        this.queryParametersValue = params;
    }
    /**
     * Pre-selects when needed the mime type for the current payload.
     */
    preselectMime() {
        const { mimeType } = this;
        const payloads = this.payloadsValue;
        if (!Array.isArray(payloads) || !payloads.length) {
            return;
        }
        const mime = [];
        let hasCurrent = false;
        payloads.forEach((item) => {
            if (item.mediaType) {
                mime.push(item.mediaType);
                if (!hasCurrent && item.mediaType === mimeType) {
                    hasCurrent = true;
                }
            }
        });
        // do not change the selection when already exist.
        if (hasCurrent) {
            return;
        }
        if (!mime.length) {
            return;
        }
        const [first] = mime;
        this.mimeType = first;
        this.notifyMime();
    }
    mediaTypeSelectHandler(e) {
        const node = e.target;
        const { value } = node;
        this.mimeType = value;
        this.notifyMime();
    }
    /**
     * Dispatches the `mimechange` event.
     */
    notifyMime() {
        this.dispatchEvent(new Event('mimechange'));
    }
    render() {
        const { request, server, endpoint } = this;
        if (!request && !server && !endpoint) {
            return html ``;
        }
        return html `
    ${this.queryParamsTemplate()}
    ${this.headersTemplate()}
    ${this.cookiesTemplate()}
    ${this.payloadTemplate()}
    `;
    }
    /**
     * @return The template for the query parameters
     */
    queryParamsTemplate() {
        const { uriParameters, hasQueryParameters } = this;
        if (!hasQueryParameters && !uriParameters.length) {
            return '';
        }
        const { request } = this;
        let queryParameters = [];
        if (request && Array.isArray(request.queryParameters)) {
            queryParameters = request.queryParameters;
        }
        if (!queryParameters.length && this.queryParametersValue && this.queryParametersValue.length) {
            queryParameters = this.queryParametersValue.map(i => i.parameter);
        }
        const content = [];
        uriParameters.forEach((param) => content.push(this.schemaItemTemplate(param, 'uri')));
        queryParameters.forEach((param) => content.push(this.schemaItemTemplate(param, 'query')));
        return this.paramsSectionTemplate('Parameters', 'parametersOpened', content.map((item, index) => {
            if (index === content.length - 1) {
                return item;
            }
            return html `
      ${item}
      <ui-divider></ui-divider>
      `;
        }));
    }
    /**
     * @return The template for the headers
     */
    headersTemplate() {
        if (!this.hasHeaders) {
            return '';
        }
        const { request } = this;
        const content = request.headers.map((param) => this.schemaItemTemplate(param, 'header'));
        return this.paramsSectionTemplate('Headers', 'headersOpened', content);
    }
    /**
     * @return The template for the cookies list section
     */
    cookiesTemplate() {
        if (!this.hasCookieParameters) {
            return '';
        }
        const { request } = this;
        const content = request.cookieParameters.map((param) => this.schemaItemTemplate(param, 'cookie'));
        return this.paramsSectionTemplate('Cookies', 'cookiesOpened', content);
    }
    /**
     * @return The template for the payload section
     */
    payloadTemplate() {
        const payload = this.payloadValue;
        if (!payload) {
            return '';
        }
        const content = html `
    ${this.payloadSelectorTemplate()}
    <api-payload-document .domainId="${payload.id}" .payload="${payload}"></api-payload-document>
    `;
        return this.paramsSectionTemplate('Request body', 'payloadOpened', content);
    }
    /**
     * @return The template for the payload media type selector.
     */
    payloadSelectorTemplate() {
        const payloads = this.payloadsValue;
        if (!Array.isArray(payloads) || payloads.length < 2) {
            return '';
        }
        const mime = [];
        payloads.forEach((item) => {
            if (item.mediaType) {
                mime.push(item.mediaType);
            }
        });
        if (!mime.length) {
            return '';
        }
        const mimeType = this.mimeType || mime[0];
        return html `
    <div class="media-type-selector">
      <span id="body-mime">Body content type</span>
      ${mime.map((item) => html `
      <label class="label-large">
        <ui-radio
          class="response-toggle"
          name="responseMime"
          value="${item}"
          .checked="${item === mimeType}"
          @change="${this.mediaTypeSelectHandler}"
        ></ui-radio>
        ${item}
      </label>
      `)}
    </div>
    `;
    }
}
__decorate([
    property({ type: Boolean, reflect: true })
], ApiRequestDocument.prototype, "parametersOpened", void 0);
__decorate([
    property({ type: Boolean, reflect: true })
], ApiRequestDocument.prototype, "headersOpened", void 0);
__decorate([
    property({ type: Boolean, reflect: true })
], ApiRequestDocument.prototype, "cookiesOpened", void 0);
__decorate([
    property({ type: Boolean, reflect: true })
], ApiRequestDocument.prototype, "payloadOpened", void 0);
__decorate([
    property({ type: String, reflect: true })
], ApiRequestDocument.prototype, "mimeType", void 0);
__decorate([
    property({ type: Object })
], ApiRequestDocument.prototype, "server", void 0);
__decorate([
    property({ type: Object })
], ApiRequestDocument.prototype, "endpoint", void 0);
//# sourceMappingURL=ApiRequestDocument.element.js.map