import { __esDecorate, __runInitializers } from "tslib";
import { LitElement, html, nothing } from 'lit';
import { property, state } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
import { statusTemplate } from '../http/HttpStatus.js';
import { RequestLogView } from '../http/RequestLog.js';
import { ErrorResponse } from '@api-client/core/models/ErrorResponse.js';
import '@github/relative-time-element';
import '../../define/http/http-request-log.js';
import '../../md/icons/ui-icon.js';
import '../../md/button/ui-button.js';
import '../../md/dropdown-list/ui-dropdown-list.js';
import '../../md/list/ui-list.js';
import '../../md/list/ui-list-item.js';
import '../../md/segmented-button/ui-segmented-button.js';
import '../../md/segmented-button/ui-segmented-button-set.js';
export var ProjectRunReportView;
(function (ProjectRunReportView) {
    ProjectRunReportView["summary"] = "summary";
    ProjectRunReportView["details"] = "details";
})(ProjectRunReportView || (ProjectRunReportView = {}));
let ProjectRunReport = (() => {
    let _classSuper = LitElement;
    let _report_decorators;
    let _report_initializers = [];
    let _report_extraInitializers = [];
    let _selectedIteration_decorators;
    let _selectedIteration_initializers = [];
    let _selectedIteration_extraInitializers = [];
    let _selectedRequest_decorators;
    let _selectedRequest_initializers = [];
    let _selectedRequest_extraInitializers = [];
    let _currentIteration_decorators;
    let _currentIteration_initializers = [];
    let _currentIteration_extraInitializers = [];
    let _currentLog_decorators;
    let _currentLog_initializers = [];
    let _currentLog_extraInitializers = [];
    let _view_decorators;
    let _view_initializers = [];
    let _view_extraInitializers = [];
    return class ProjectRunReport extends _classSuper {
        static {
            const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
            _report_decorators = [property({ type: Object })];
            _selectedIteration_decorators = [state()];
            _selectedRequest_decorators = [state()];
            _currentIteration_decorators = [state()];
            _currentLog_decorators = [state()];
            _view_decorators = [state()];
            __esDecorate(this, null, _report_decorators, { kind: "accessor", name: "report", static: false, private: false, access: { has: obj => "report" in obj, get: obj => obj.report, set: (obj, value) => { obj.report = value; } }, metadata: _metadata }, _report_initializers, _report_extraInitializers);
            __esDecorate(this, null, _selectedIteration_decorators, { kind: "accessor", name: "selectedIteration", static: false, private: false, access: { has: obj => "selectedIteration" in obj, get: obj => obj.selectedIteration, set: (obj, value) => { obj.selectedIteration = value; } }, metadata: _metadata }, _selectedIteration_initializers, _selectedIteration_extraInitializers);
            __esDecorate(this, null, _selectedRequest_decorators, { kind: "accessor", name: "selectedRequest", static: false, private: false, access: { has: obj => "selectedRequest" in obj, get: obj => obj.selectedRequest, set: (obj, value) => { obj.selectedRequest = value; } }, metadata: _metadata }, _selectedRequest_initializers, _selectedRequest_extraInitializers);
            __esDecorate(this, null, _currentIteration_decorators, { kind: "accessor", name: "currentIteration", static: false, private: false, access: { has: obj => "currentIteration" in obj, get: obj => obj.currentIteration, set: (obj, value) => { obj.currentIteration = value; } }, metadata: _metadata }, _currentIteration_initializers, _currentIteration_extraInitializers);
            __esDecorate(this, null, _currentLog_decorators, { kind: "accessor", name: "currentLog", static: false, private: false, access: { has: obj => "currentLog" in obj, get: obj => obj.currentLog, set: (obj, value) => { obj.currentLog = value; } }, metadata: _metadata }, _currentLog_initializers, _currentLog_extraInitializers);
            __esDecorate(this, null, _view_decorators, { kind: "accessor", name: "view", static: false, private: false, access: { has: obj => "view" in obj, get: obj => obj.view, set: (obj, value) => { obj.view = value; } }, metadata: _metadata }, _view_initializers, _view_extraInitializers);
            if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
        }
        #report_accessor_storage = __runInitializers(this, _report_initializers, void 0);
        get report() { return this.#report_accessor_storage; }
        set report(value) { this.#report_accessor_storage = value; }
        #selectedIteration_accessor_storage = (__runInitializers(this, _report_extraInitializers), __runInitializers(this, _selectedIteration_initializers, void 0));
        /**
         * The index of the selected iteration, if any.
         */
        get selectedIteration() { return this.#selectedIteration_accessor_storage; }
        set selectedIteration(value) { this.#selectedIteration_accessor_storage = value; }
        #selectedRequest_accessor_storage = (__runInitializers(this, _selectedIteration_extraInitializers), __runInitializers(this, _selectedRequest_initializers, void 0));
        /**
         * The index of the selected request, if any
         */
        get selectedRequest() { return this.#selectedRequest_accessor_storage; }
        set selectedRequest(value) { this.#selectedRequest_accessor_storage = value; }
        #currentIteration_accessor_storage = (__runInitializers(this, _selectedRequest_extraInitializers), __runInitializers(this, _currentIteration_initializers, void 0));
        /**
         * The currently rendered iteration.
         */
        get currentIteration() { return this.#currentIteration_accessor_storage; }
        set currentIteration(value) { this.#currentIteration_accessor_storage = value; }
        #currentLog_accessor_storage = (__runInitializers(this, _currentIteration_extraInitializers), __runInitializers(this, _currentLog_initializers, void 0));
        get currentLog() { return this.#currentLog_accessor_storage; }
        set currentLog(value) { this.#currentLog_accessor_storage = value; }
        #view_accessor_storage = (__runInitializers(this, _currentLog_extraInitializers), __runInitializers(this, _view_initializers, ProjectRunReportView.summary));
        get view() { return this.#view_accessor_storage; }
        set view(value) { this.#view_accessor_storage = value; }
        willUpdate(cp) {
            super.updated(cp);
            if (cp.has('report')) {
                this.processReport();
            }
        }
        processReport() {
            const { report } = this;
            if (!report) {
                this.selectedIteration = undefined;
                this.selectedRequest = undefined;
                this.currentIteration = undefined;
                this.currentLog = undefined;
                return;
            }
            this.selectedIteration = 0;
            this.selectedRequest = 0;
            const [iteration] = report.iterations;
            this.currentIteration = iteration;
            this.currentLog = iteration && iteration.executed && iteration.executed[0];
        }
        handleIterationSelection(e) {
            const element = e.detail.item;
            const { index } = element.dataset;
            if (!index) {
                return;
            }
            const typed = Number(index);
            if (Number.isNaN(typed)) {
                return;
            }
            this.selectIteration(typed);
        }
        selectIteration(index) {
            const { report } = this;
            if (!report) {
                return;
            }
            const item = report.iterations[index];
            if (!item) {
                return;
            }
            this.selectedIteration = index;
            this.currentIteration = item;
            this.selectedRequest = 0;
            this.currentLog = item.executed && item.executed[0];
        }
        handleRequestSelection(e) {
            const element = e.detail.item;
            const { index } = element.dataset;
            if (!index) {
                return;
            }
            const typed = Number(index);
            if (Number.isNaN(typed)) {
                return;
            }
            this.selectRequest(typed);
        }
        selectRequest(index) {
            const { currentIteration } = this;
            if (!currentIteration) {
                return;
            }
            const item = currentIteration.executed[index];
            if (!item) {
                return;
            }
            this.selectedRequest = index;
            this.currentLog = item;
        }
        handleViewSelection(e) {
            if (!e.detail.selected) {
                return;
            }
            const button = e.detail.button;
            const view = button.dataset.value;
            if (view) {
                this.view = view;
            }
        }
        handleLinkClick(e) {
            const node = e.target;
            const { iterationIndex, requestIndex, target } = node.dataset;
            if (!requestIndex || !iterationIndex) {
                return;
            }
            const iteration = Number(iterationIndex);
            const request = Number(requestIndex);
            if (Number.isNaN(request) || Number.isNaN(iteration)) {
                return;
            }
            this.selectIteration(iteration);
            this.selectRequest(request);
            this.view = ProjectRunReportView.details;
            if (target) {
                this.selectLogView(target);
            }
        }
        handleLinkKeyDown(e) {
            if (['Enter', 'Space'].includes(e.code)) {
                this.handleLinkClick(e);
            }
        }
        async selectLogView(view) {
            await this.updateComplete;
            const node = this.shadowRoot?.querySelector('http-request-log');
            if (!node) {
                return;
            }
            node.view = view;
        }
        render() {
            const { report } = this;
            if (!report) {
                return html ``;
            }
            return html ` ${this.renderHeader(report)} ${this.renderView()} `;
        }
        renderHeader(report) {
            return html ` <div class="header">${this.renderCurrentSelectors(report)} ${this.renderViewToggle()}</div> `;
        }
        renderCurrentSelectors(report) {
            if (this.view === ProjectRunReportView.summary) {
                return nothing;
            }
            const hasIterations = report.iterations.length > 1;
            return html `
      ${hasIterations ? this.renderInteractionsList(report.iterations) : nothing} ${this.renderRequestsList()}
    `;
        }
        renderViewToggle() {
            const { view } = this;
            return html `
      <div class="view-toggle">
        <ui-segmented-button-set @select="${this.handleViewSelection}">
          <ui-segmented-button
            .selected="${view === ProjectRunReportView.summary}"
            title="Shows summary of the run report"
            data-value="summary"
            >Summary</ui-segmented-button
          >
          <ui-segmented-button
            .selected="${view === ProjectRunReportView.details}"
            title="Shows detailed response information for each request"
            data-value="details"
            >Details</ui-segmented-button
          >
        </ui-segmented-button-set>
      </div>
    `;
        }
        renderInteractionsList(iterations) {
            const { selectedIteration = 0 } = this;
            const iteration = iterations[selectedIteration];
            const index = iteration ? iteration.index + 1 : 1;
            return html `
      <ui-dropdown-list
        verticalAlign="top"
        class="iterations-dropdown"
        closeOnOutsideClick
        @select="${this.handleIterationSelection}"
      >
        <ui-button color="tonal">
          <ui-icon slot="icon" icon="arrowDropDown"></ui-icon>
          Iteration #${index}
        </ui-button>
        <ui-list slot="dropdown" role="menu" aria-label="Iterations list">
          ${iterations.map((current) => this.renderIterationOption(current.index))}
        </ui-list>
      </ui-dropdown-list>
    `;
        }
        renderIterationOption(index) {
            const classes = {
                'iteration-option': true,
                'highlight': this.selectedIteration === index,
            };
            return html `
      <ui-list-item role="menuitem" data-index="${index}" class="${classMap(classes)}">
        Iteration #${index + 1}
      </ui-list-item>
    `;
        }
        renderRequestsList() {
            const { currentIteration, selectedRequest = 0 } = this;
            if (!currentIteration) {
                return this.renderEmptyRequestsList();
            }
            if (!currentIteration.executed || !currentIteration.executed.length) {
                return this.renderEmptyRequestsList();
            }
            const options = currentIteration.executed.map((item, index) => this.renderRequestsOption(item, index));
            const item = currentIteration.executed[selectedRequest];
            const title = (item.request && item.request.url) || `Request #${selectedRequest}`;
            return html `
      <ui-dropdown-list
        verticalAlign="top"
        class="history-dropdown"
        closeOnOutsideClick
        @select="${this.handleRequestSelection}"
      >
        <ui-button color="tonal" title="${title}">
          <ui-icon slot="icon" icon="arrowDropDown"></ui-icon>
          <span class="request-title-dropdown">${title}</span>
        </ui-button>
        <ui-list slot="dropdown" role="menu" aria-label="History list"> ${options} </ui-list>
      </ui-dropdown-list>
    `;
        }
        renderEmptyRequestsList() {
            return html `
      <ui-button color="tonal" disabled>
        <ui-icon slot="icon" icon="arrowDropDown"></ui-icon>
        No requests
      </ui-button>
    `;
        }
        renderRequestsOption(item, index) {
            const title = (item.request && item.request.url) || `Request #${index}`;
            const error = !item.response || ErrorResponse.isErrorResponse(item.response);
            const classes = {
                'history-option': true,
                error,
                'highlight': this.selectedRequest === index,
            };
            let status = 0;
            let statusText;
            let duration = 0;
            if (!error) {
                const typed = item.response;
                status = typed.status;
                statusText = typed.statusText;
                duration = typed.loadingTime;
            }
            return html `
      <ui-list-item lines="two" role="menuitem" data-index="${index}" class="${classMap(classes)}">
        <div class="history-label">
          <span class="label-value">${statusTemplate(status, statusText)} ${duration} ms</span>
        </div>
        <span slot="supporting-text">${title}</span>
      </ui-list-item>
    `;
        }
        renderView() {
            switch (this.view) {
                case ProjectRunReportView.details:
                    return this.renderLog();
                case ProjectRunReportView.summary:
                    return this.renderSummary();
                default:
                    return html `<p>Invalid view selection.</p>`;
            }
        }
        renderLog() {
            const { currentLog } = this;
            return html `
      <div class="response">
        ${currentLog ? html `<http-request-log .httpLog="${currentLog}"></http-request-log>` : ''}
      </div>
    `;
        }
        renderSummary() {
            const { report } = this;
            if (!report) {
                return html `<p>Report is not set.</p>`;
            }
            const { iterations, ended } = report;
            const de = new Date(ended);
            return html `
      <div class="summary-header">
        Run ended <relative-time slot="supporting-text" datetime="${de.toISOString()}"></relative-time>
      </div>
      ${iterations.map((iteration) => this.renderIterationSummary(iteration))}
    `;
        }
        renderIterationSummary(iteration) {
            const { error, executed, index } = iteration;
            return html ` ${error ? this.renderIterationError() : this.renderIterationSummaryTable(index, executed)} `;
        }
        renderIterationError() {
            return html ` <p class="iteration-error">The iteration was not executed due to an error.</p> `;
        }
        renderIterationSummaryTable(iterationIndex, executed) {
            const failedIndex = [];
            executed.forEach((item, index) => {
                const { assertions = [] } = item;
                const hasFailed = assertions.find((i) => !i.ok);
                if (hasFailed) {
                    failedIndex.push(`#${index + 1}`);
                }
            });
            const formatter = new Intl.ListFormat(undefined, { style: 'long', type: 'conjunction' });
            return html `
      <table class="execution-table">
        <caption>
          Iteration #${iterationIndex + 1}. Failed requests:
          ${failedIndex.length ? formatter.format(failedIndex) : 'none'}.
        </caption>
        <thead>
          <tr>
            <th scope="col" class="request">HTTP request</th>
            <th scope="col" class="status">Status</th>
            <th scope="col" class="time">Time</th>
            <th scope="col" class="assertions">Assertions</th>
          </tr>
        </thead>
        <tbody>
          ${executed.map((item, requestIndex) => this.renderSummaryTableRow(item, iterationIndex, requestIndex))}
        </tbody>
      </table>
    `;
        }
        renderSummaryTableRow(item, iterationIndex, requestIndex) {
            const { assertions = [], request, response } = item;
            if (!request) {
                return html `
        <tr>
          <td colspan="3">The request was not executed (missing request info)</td>
        </tr>
      `;
            }
            const error = !item.response || ErrorResponse.isErrorResponse(item.response);
            let status;
            let duration = 0;
            if (error) {
                status = html `Errored`;
            }
            else if (response) {
                status = statusTemplate(response.status, response.statusText);
                duration = response.loadingTime;
            }
            else {
                status = html `Unknown`;
            }
            const successAssertions = (item.assertions || []).filter((i) => i.ok);
            const hasFailed = assertions.length - successAssertions.length !== 0;
            return html `
      <tr>
        <td class="request">
          <span class="http-label pill" data-method="${(request.method || 'get').toLowerCase()}"
            >${request.method}</span
          >
          <span
            class="link"
            title="Open details"
            data-iteration-index="${iterationIndex}"
            data-request-index="${requestIndex}"
            @click="${this.handleLinkClick}"
            @keydown="${this.handleLinkKeyDown}"
            tabindex="0"
            >${request.url}</span
          >
        </td>
        <td class="status">${status}</td>
        <td class="time">${duration}ms</td>
        <td class="assertions">
          <span
            class="link"
            title="Open assertion details"
            data-iteration-index="${iterationIndex}"
            data-request-index="${requestIndex}"
            data-target="${RequestLogView.assertions}"
            @click="${this.handleLinkClick}"
            @keydown="${this.handleLinkKeyDown}"
            tabindex="0"
            >${successAssertions.length}/${assertions.length}</span
          >
          ${hasFailed ? html `<div class="badge small"></div>` : ''}
        </td>
      </tr>
    `;
        }
        constructor() {
            super(...arguments);
            __runInitializers(this, _view_extraInitializers);
        }
    };
})();
/**
 * An element that renders the execution log of the project runner with the IProjectExecutionLog.
 */
export default ProjectRunReport;
//# sourceMappingURL=ProjectRunReport.js.map