import { html, TemplateResult } from 'lit'
import { AmfNamespace } from '@api-client/core/amf/definitions/Namespace.js'
import { AmfMixin } from '@api-client/core/amf/AmfMixin.js'
import { AmfDemoPage } from './lib/AmfDemoPage.js'
import { reactive } from '../../src/decorators/index.js'
import type { ApiNavigationEvent } from '../../src/events/amf/NavigationEvents.js'
import { ServerType } from '../../src/amf/types.js'
// import { WebProxyBindings } from '../../src/bindings/web/WebProxyBindings.js'
// import env from '../env.js'
import '../../src/define/amf/api-resource-document.js'
import '../../src/define/amf/api-request.js'
import '../../src/define/amf/api-server-picker.js'
import '../../src/md/checkbox/ui-checkbox.js'
import '../../src/md/dialog/ui-dialog.js'

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

class AmfHelper extends AmfMixin(Object) {}

class ComponentPage extends AmfDemoPage {
  @reactive() accessor editorOpened: boolean | undefined

  @reactive() accessor editorOperation: string | undefined

  @reactive() accessor selectedId: string | undefined

  @reactive() accessor selectedType: string | undefined

  @reactive() accessor selectedOperation: string | undefined

  @reactive() accessor tryItButton: boolean | undefined

  @reactive() accessor tryItPanel: boolean | undefined

  @reactive() accessor overrideBaseUri: boolean | undefined

  @reactive() accessor serverType: string | undefined

  @reactive() accessor serverValue: string | undefined

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

  constructor() {
    super()

    this.componentName = 'api-endpoint-document'
    this.tryItButton = true
    ;[
      ['httpbin', 'httpbin.org'],
      ['google-drive-api', 'Google Drive'],
      ['multi-server', 'Multiple servers'],
      ['nexmo-sms-api', 'Nexmo SMS API'],
      ['appian-api', 'Applian API'],
      ['APIC-15', 'APIC-15'],
      ['SE-10469', 'SE-10469'],
      ['SE-11415', 'SE-11415'],
      ['async-api', 'async-api'],
      ['Petstore-v2', 'Petstore OAS API'],
      ['api-keys', 'API key (OAS)'],
      ['oauth-flows', 'OAuth 2 flows'],
      ['oas-bearer', 'Bearer token'],
      ['oauth-pkce', 'OAuth 2 PKCE'],
      ['secured-unions', 'Secured unions'],
      ['secured-api', 'Secured API'],
      ['SE-12957', 'SE-12957: OAS query parameters documentation'],
      ['SE-12959', 'SE-12959: OAS summary field'],
      ['SE-12752', 'SE-12752: Query string'],
      ['SE-12957', 'SE-12957: Path in an operation'],
      ['oas-callbacks', 'OAS 3 callbacks'],
      ['APIC-553', 'APIC-553'],
      ['APIC-560', 'APIC-560'],
      ['APIC-582', 'APIC-582'],
      ['APIC-650', 'APIC-650'],
    ].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()
  }

  get baseUri(): string | undefined {
    const { serverValue, serverType } = this
    if (['custom', 'uri'].includes(serverType as string)) {
      return serverValue
    }
    return undefined
  }

  get serverId(): string | undefined {
    const { serverValue, serverType, selectedId } = this
    if (!serverValue || ['custom', 'uri'].includes(serverType as string)) {
      return undefined
    }
    const helper = new AmfHelper()
    helper.amf = this.amf

    const servers = helper._getServers({ endpointId: selectedId })
    if (!Array.isArray(servers)) {
      return undefined
    }
    const srv = servers.find((item) => {
      const url = helper._getValue(item, AmfNamespace.aml.vocabularies.core.urlTemplate)
      return url === serverValue
    })
    if (srv) {
      return srv['@id']
    }
    return undefined
  }

  _serverHandler(e: CustomEvent): void {
    const { value, type } = e.detail
    this.serverType = type
    this.serverValue = value
  }

  override _navChanged(e: ApiNavigationEvent): void {
    const { domainId, domainType, passive, parentId } = e.detail
    if (passive) {
      return
    }
    if (domainType === 'resource') {
      this.selectedId = domainId
      this.selectedType = domainType
      this.selectedOperation = undefined
    } else if (domainType === 'operation') {
      this.selectedId = parentId
      this.selectedType = 'endpoint'
      this.selectedOperation = domainId
    } else {
      this.selectedId = undefined
      this.selectedType = undefined
      this.selectedOperation = undefined
    }
  }

  tryitHandler(e: CustomEvent): void {
    const { id } = e.detail
    this.editorOperation = id
    this.editorOpened = true
  }

  editorCloseHandler(): void {
    this.editorOperation = undefined
    this.editorOpened = false
  }

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

  demoTemplate(): TemplateResult {
    const { loaded } = this
    return html`
      <section class="centered large demo-region">${this.serverSelectorTemplate()}</section>
      ${!loaded ? html`<p>Load an API model first.</p>` : this.loadedTemplate()}
    `
  }

  loadedTemplate(): TemplateResult {
    return html` ${this.componentTemplate()} ${this.requestEditorDialogTemplate()} `
  }

  componentTemplate(): TemplateResult {
    const { selectedId, selectedOperation, tryItButton, tryItPanel, overrideBaseUri, baseUri, serverId } = this
    if (!selectedId) {
      return html`<p>Select API operation in the navigation</p>`
    }
    let finalBaseUri: string | undefined
    if (baseUri) {
      finalBaseUri = baseUri
    } else if (overrideBaseUri) {
      finalBaseUri = 'https://custom.api.com'
    }
    return html`
      <section class="demo-section">
        <api-resource-document
          .domainId="${selectedId}"
          .operationId="${selectedOperation}"
          .serverId="${serverId}"
          .redirectUri="${this.redirectUri}"
          .serverType="${this.serverType}"
          .serverValue="${this.serverValue}"
          ?tryItButton="${tryItButton}"
          ?tryItPanel="${tryItPanel}"
          .baseUri="${finalBaseUri}"
          slot="content"
          @tryit="${this.tryitHandler}"
        >
        </api-resource-document>
      </section>

      <section class="demo-section">
        <p class="block" id="mainOptionsLabel">Options</p>
        <label class="label-large">
          <ui-checkbox
            @change="${this._toggleBooleanOption}"
            ?checked="${tryItButton}"
            name="tryItButton"
            aria-describedby="mainOptionsLabel"
          ></ui-checkbox>
          Render try it
        </label>

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

        <label class="label-large">
          <ui-checkbox
            @change="${this._toggleBooleanOption}"
            ?checked="${overrideBaseUri}"
            name="overrideBaseUri"
            aria-describedby="mainOptionsLabel"
          ></ui-checkbox>
          Custom base URI
        </label>
      </section>
    `
  }

  requestEditorDialogTemplate(): TemplateResult {
    return html`
      <ui-dialog modal @close="${this.editorCloseHandler}" .open="${this.editorOpened || false}" class="request-dialog">
        <span slot="title">API request</span>
        <api-request .domainId="${this.editorOperation}" urlLabel allowHideOptional .redirectUri="${this.redirectUri}">
        </api-request>
        <ui-text-button slot="button" value="dismiss">Close</ui-text-button>
      </ui-dialog>
    `
  }

  /**
   * @returns A template for the server selector
   */
  serverSelectorTemplate(): TemplateResult {
    const { serverType, serverValue } = this
    return html` <api-server-picker
      .value="${serverValue}"
      .type="${serverType as ServerType}"
      auto
      custom
      @apiserverchanged="${this._serverHandler}"
    ></api-server-picker>`
  }
}
const instance = new ComponentPage()
instance.render()
