import { html, TemplateResult } from 'lit';
import { IApplication } from '@api-client/core/build/browser.js';
import { AmfDemoPage } from './lib/AmfDemoPage.js';
import { reactive } from '../../src/lib/decorators.js';
import { AmfTypes, ApiNavigationEvent, ServerChangeEvent } from '../../src/index.js';
import { WebProxyBindings } from '../../src/bindings/web/WebProxyBindings.js';
import env from '../env.js';
import '../../src/define/amf/api-navigation.js';
import '../../src/define/amf/api-request.js';
import '../../src/define/ui/ui-list-item.js';
import '../../src/define/ui/ui-checkbox.js';

const AppInfo: IApplication = { code: 'demo', name: 'Demo', 'version': '0' };

class ComponentDemo extends AmfDemoPage {
  @reactive() domainId?: string;

  @reactive() domainType?: AmfTypes.SelectionType;

  @reactive() allowCustom: boolean;

  @reactive() allowCustomBaseUri: boolean;
  
  @reactive() allowHideOptional: boolean;

  @reactive() allowDisableParams: boolean;

  @reactive() urlEditor: boolean;

  @reactive() renderCustomServer: boolean;

  @reactive() noServerSelector: boolean;

  @reactive() urlLabel: boolean;

  @reactive() selectedServerValue?: string;

  http = new WebProxyBindings(AppInfo, `${env.proxyUri}/open`);

  constructor() {
    super();

    this.componentName = 'api-request';
    this.allowCustom = false;
    this.allowHideOptional = true;
    this.allowDisableParams = true;
    this.renderCustomServer = false;
    this.noServerSelector = false;
    this.allowCustomBaseUri = false;
    this.urlLabel = false;
    this.urlEditor = true;

    this.apis = [];
    [
      ['google-drive-api', 'Google Drive'],
      ['httpbin', 'httpbin.org'],
      ['demo-api', 'Demo API'],
      ['multi-server', 'Multiple servers'],
      ['appian-api', 'Applian API'],
      ['loan-microservice', 'Loan microservice (OAS)'],
      ['array-body', 'Request body with an array (reported issue)'],
      ['SE-12042', 'Default values issue (SE-12042)'],
      ['SE-12224', 'Scope is not an array issues (SE-12224)'],
      ['APIC-168', 'Custom scheme support (APIC-168)'],
      ['async-api', 'AsyncAPI'],
      ['APIC-289', 'OAS param names (APIC-289)'],
      ['api-keys', 'API key'],
      ['oas-demo', 'OAS Demo API'],
      ['oauth-flows', 'OAS OAuth Flow'],
      ['oas-bearer', 'OAS Bearer'],
      ['secured-api', 'Security demo'],
      ['21143', '21143'],
      ['annotated-parameters', 'annotated-parameters'],
      ['secured-unions', 'Secured unions']
    ].forEach(([file, label]) => {
      this.apis.push({
        file: `models/${file}.json`,
        label,
      })
    });

    this.autoLoad();
  }

  override async autoLoad(): Promise<void> {
    await this.http.initialize();
    return super.autoLoad();
  }

  _navChanged(e: ApiNavigationEvent): void {
    this.domainId = undefined;
    this.domainType = undefined;
    const { domainId, domainType } = e.detail;
    if (domainType === 'operation') {
      this.domainId = domainId;
      this.domainType = domainType;
    }
  }

  _addCustomServers(): TemplateResult {
    if (!this.renderCustomServer) {
      return html``;
    }
    return html`
    <div class="other-section" slot="custom-base-uri">Other options</div>
    <ui-list-item
      slot="custom-base-uri"
      data-value="http://mocking.com"
    >Mocking service</ui-list-item>
    <ui-list-item
      slot="custom-base-uri"
      data-value="http://customServer.com2"
    >Custom instance</ui-list-item>`;
  }

  _serverChangeHandler(e: ServerChangeEvent): void {
    const { value } = e.detail;
    // The parent keeps current selection which is then passed back to the
    // server selector. In API Console, the console holds the selected value
    // so it can be distributed between api-documentation and api-request,
    // even when panels are re-rendered. This way the application don't loose
    // track of that was selected.
    // The selector take cares of a situation when current selection is no
    // longer available and clears the state.
    this.selectedServerValue = value;
  }

  contentTemplate(): TemplateResult {
    return html`
      <a href="./">Back</a>
      ${this.demoTemplate()}
    `;
  }

  demoTemplate(): TemplateResult {
    const { loaded } = this;
    return html`
      ${!loaded ? html`<p>Load an API model first.</p>` : this.loadedTemplate()}
    `;
  }

  loadedTemplate(): TemplateResult {
    const {
      redirectUri,
      allowCustom,
      allowHideOptional,
      allowDisableParams,
      domainId,
      noServerSelector,
      allowCustomBaseUri,
      urlEditor,
      urlLabel,
      selectedServerValue,
    } = this;
    return html`
    <section class="demo-section">
      <api-request
        .domainId="${domainId}"
        ?allowCustom="${allowCustom}"
        ?allowHideOptional="${allowHideOptional}"
        ?urlEditor="${urlEditor}"
        ?urlLabel="${urlLabel}"
        ?noServerSelector="${noServerSelector}"
        ?allowCustomBaseUri="${allowCustomBaseUri}"
        .redirectUri="${redirectUri}"
        .serverValue="${selectedServerValue}"
        @apiserverchanged="${this._serverChangeHandler}"
      >
        ${this._addCustomServers()}
      </api-request>
    </section>

    <section class="demo-section">
      <p id="mainOptionsLabel">Options</p>
      <label class="label-large">
        <ui-checkbox
          @change="${this._toggleBooleanOption}" 
          ?checked="${allowCustom}"
          name="allowCustom"
          aria-describedby="mainOptionsLabel"
          aria-label="Allow custom"
        ></ui-checkbox>
        Allow custom
      </label>

      <label class="label-large">
        <ui-checkbox
          @change="${this._toggleBooleanOption}" 
          ?checked="${allowHideOptional}"
          name="allowHideOptional"
          aria-describedby="mainOptionsLabel"
          aria-label="Allow hide optional"
        ></ui-checkbox>
        Allow hide optional
      </label>

      <label class="label-large">
        <ui-checkbox
          @change="${this._toggleBooleanOption}" 
          ?checked="${allowDisableParams}"
          name="allowDisableParams"
          aria-describedby="mainOptionsLabel"
          aria-label="Allow disable params"
        ></ui-checkbox>
        Allow disable params
      </label>

      <label class="label-large">
        <ui-checkbox
          @change="${this._toggleBooleanOption}" 
          ?checked="${urlEditor}"
          name="urlEditor"
          aria-describedby="mainOptionsLabel"
          aria-label="URL editor"
        ></ui-checkbox>
        URL editor
      </label>

      <label class="label-large">
        <ui-checkbox
          @change="${this._toggleBooleanOption}" 
          ?checked="${urlLabel}"
          name="urlLabel"
          aria-describedby="mainOptionsLabel"
          aria-label="URL label"
        ></ui-checkbox>
        URL label
      </label>

      <label class="label-large">
        <ui-checkbox
          @change="${this._toggleBooleanOption}" 
          ?checked="${this.renderCustomServer}"
          name="renderCustomServer"
          aria-describedby="mainOptionsLabel"
          aria-label="Add custom servers"
        ></ui-checkbox>
        Add custom servers
      </label>

      <label class="label-large">
        <ui-checkbox
          @change="${this._toggleBooleanOption}" 
          ?checked="${allowCustomBaseUri}"
          name="allowCustomBaseUri"
          aria-describedby="mainOptionsLabel"
          aria-label="Allow Custom Base Uri"
        ></ui-checkbox>
        Allow Custom Base Uri
      </label>

      <label class="label-large">
        <ui-checkbox
          @change="${this._toggleBooleanOption}" 
          ?checked="${noServerSelector}"
          name="noServerSelector"
          aria-describedby="mainOptionsLabel"
          aria-label="No Server Selector"
        ></ui-checkbox>
        No Server Selector
      </label>
    </section>
    `;
  }
}
const instance = new ComponentDemo();
instance.render();
