import Clipboard from 'clipboard'
import gql from 'graphql-tag'
import { css, html } from 'lit'
import { customElement, property, queryAll } from 'lit/decorators.js'
import { connect } from 'pwa-helpers/connect-mixin.js'

import { APPLICATION_TYPES } from '../../constants/application'

import { client } from '@operato/graphql'
import { navigate, PageView, store } from '@operato/shell'

@customElement('application-page')
class Application extends connect(store)(PageView) {
  static styles = [
    css`
      :host {
        display: flex;
        flex-direction: column;
        overflow-y: auto;
        position: relative;
        background-color: var(--main-section-background-color);
        padding: var(--padding-wide);
      }
      h2 {
        display: flex;
        align-items: center;
        margin: var(--title-margin);
        font: var(--title-font);
        color: var(--title-text-color);
      }
      [page-description] {
        margin: var(--page-description-margin);
        font: var(--page-description-font);
        color: var(--page-description-color);
      }
      [icon] {
        position: absolute;
        top: 10px;
        right: 10px;
        max-width: 80px;
      }
      [icon] img {
        max-width: 100%;
        max-height: 100%;
      }
      label {
        font: var(--label-font);
        color: var(--label-color);
        text-transform: var(--label-text-transform);
      }
      input,
      select {
        border: var(--border-dark-color);
        border-radius: var(--border-radius);
        margin: var(--input-margin);
        padding: var(--input-padding);
        font: var(--input-font);
        flex: 1;
      }
      select:focus,
      input:focus,
      button {
        outline: none;
      }
      form {
        max-width: var(--content-container-max-width);
      }
      [fieldset-container] {
        background-color: var(--theme-white-color);
        margin: var(--margin-wide) 0 var(--margin-default) 0;
        padding: var(--padding-default);
        border-radius: var(--border-radius);
        box-shadow: var(--box-shadow);
      }
      [fieldset-container] fieldset {
        margin: 0;
        margin-top: -15px;
      }
      fieldset {
        border-radius: var(--border-radius);
        border: var(--border-dark-color);
        margin: var(--fieldset-margin);
        padding: var(--fieldset-padding);
      }
      legend {
        padding: var(--legend-padding);
        font-weight: bold;
        color: var(--legend-color);
      }
      [field-2column] {
        display: grid;
        grid-template-columns: 1fr 1fr;
        grid-gap: 15px;
      }
      [field] {
        display: flex;
        flex-direction: column;
        position: relative;
      }
      [grid-span] {
        grid-column: span 2;
      }
      [button-in-field] {
        position: absolute;
        top: 24px;
        right: 4px;
      }
      [input-hint] {
        font: var(--input-hint-font);
        color: var(--input-hint-color);
      }
      [danger] {
        --mdc-theme-primary: var(--mdc-danger-button-primary-color);
      }
      .button-container {
        margin-top: var(--margin-wide);
        text-align: right;
      }
      .button-container mwc-button {
        margin-left: var(--margin-narrow);
      }
      @media screen and (max-width: 480px) {
        [field] {
          grid-column: span 2;
        }
      }
    `
  ]

  @property({ type: Object }) application: any
  @queryAll('[clipboard-copy]') copybuttons
  private clipboard?: Clipboard

  get context() {
    return {
      title: {
        icon: 'apps',
        text: this.application.name
      }
    }
  }

  render() {
    var app = this.application || {}

    return html`
      <div>
        <h2><mwc-icon>apps</mwc-icon>&nbsp;${app.name}</h2>
        <p page-description>${app.description}</p>
      </div>

      <div icon>
        <img src=${app.icon} />
      </div>

      <form>
        <div fieldset-container>
          <fieldset>
            <legend>application</legend>
            <div field-2column>
              <div field grid-span>
                <label for="name">app name</label>
                <input id="name" type="text" name="name" .value=${app.name} />
              </div>

              <div field grid-span>
                <label for="description">description</label>
                <input id="description" type="text" name="description" .value=${app.description} />
              </div>

              <div field grid-span>
                <label for="email">contact email</label>
                <input id="email" type="text" name="email" .value=${app.email} />
              </div>

              <div field grid-span>
                <label for="type-selector">type</label>
                <select id="type-selector" name="type">
                  ${APPLICATION_TYPES.map(
                    type =>
                      html`<option value="${app.type}" ?selected="${type === app.type ? true : false}">${type}</option>`
                  )}
                </select>
              </div>

              <div field grid-span>
                <label for="url">application URL</label>
                <input id="url" type="text" name="url" .value=${app.url} />
              </div>

              <div field grid-span>
                <label for="icon">icon</label>
                <input id="icon" type="text" name="icon" .value=${app.icon} />
              </div>

              <div field grid-span>
                <label for="redirect-url">redirect URL</label>
                <input id="redirect-url" type="text" name="redirectUrl" .value=${app.redirectUrl} />
              </div>

              <div field grid-span>
                <label for="webhook">webhook</label>
                <input id="webhook" type="text" name="webhook" .value=${app.webhook} />
              </div>

              <div field grid-span>
                <label for="available-scopes">available-scopes</label>
                <input id="available-scopes" type="text" .value=${app.availableScopes} readonly />
              </div>

              <div field grid-span>
                <label for="auth-url">auth URL</label>
                <input id="auth-url" type="text" .value=${app.authUrl} readonly />
                <mwc-button
                  dense
                  unelevated
                  button-in-field
                  clipboard-copy
                  @click=${e => e.preventDefault()}
                  label="copy"
                ></mwc-button>
                The endpoint for authorization server. This is used to get the authorization code.
              </div>

              <div field grid-span>
                <label for="access-token-url">access token URL</label>
                <input id="access-token-url" type="text" .value=${app.accessTokenUrl} readonly />
                <mwc-button
                  dense
                  unelevated
                  button-in-field
                  clipboard-copy
                  @click=${e => e.preventDefault()}
                  label="copy"
                ></mwc-button>
                The endpoint for authentication server. This is used to exchange the authorization code for an access
                token.
              </div>
            </div>
          </fieldset>
        </div>

        <div fieldset-container>
          <fieldset>
            <legend>credentials</legend>
            <div field-2column>
              <div field grid-span>
                <label for="app-key">appKey</label>
                <input id="app-key" type="text" .value=${app.appKey} readonly />
                <mwc-button
                  dense
                  unelevated
                  button-in-field
                  clipboard-copy
                  @click=${e => e.preventDefault()}
                  label="copy"
                ></mwc-button>
              </div>

              <div field grid-span>
                <label for="app-secret">appSecret</label>
                <input id="app-secret" type="text" .value=${app.appSecret} readonly />
                <mwc-button
                  dense
                  unelevated
                  button-in-field
                  clipboard-copy
                  @click=${e => e.preventDefault()}
                  label="copy"
                ></mwc-button>
              </div>
            </div>
          </fieldset>
        </div>

        <div class="button-container">
          <mwc-button raised danger label="delete this app" @click=${this.deleteApplication.bind(this)}></mwc-button>
          <mwc-button raised label="update" @click=${this.updateApplication.bind(this)}></mwc-button>
          <mwc-button outlined label="generate new secret"></mwc-button>
        </div>
      </form>
    `
  }

  firstUpdated() {
    this.clipboard = new Clipboard(this.copybuttons, {
      target: (trigger => trigger.parentElement.querySelector('input')) as any
    })
  }

  async pageUpdated(changes, lifecycle, before) {
    if (this.active) {
      await this.fetchApplication()
    }
  }

  async fetchApplication() {
    const response = await client.query({
      query: gql`
        query ($id: String!) {
          application(id: $id) {
            id
            name
            description
            email
            url
            icon
            redirectUrl
            authUrl
            accessTokenUrl
            webhook
            availableScopes
            appKey
            appSecret
            type
          }
        }
      `,
      variables: {
        id: this.lifecycle.resourceId
      }
    })

    this.application = response.data.application
  }

  async updateApplication(e) {
    e.preventDefault()

    const form = this.renderRoot.querySelector('form') as HTMLFormElement
    const formData = new FormData(form)

    const patch = Array.from(formData.entries()).reduce((patch, [key, value]) => {
      patch[key] = value
      return patch
    }, {})

    const id = this.lifecycle.resourceId

    const response = await client.mutate({
      mutation: gql`
        mutation ($id: String!, $patch: ApplicationPatch!) {
          updateApplication(id: $id, patch: $patch) {
            id
            name
            description
            email
            url
            icon
            redirectUrl
            webhook
            appKey
            appSecret
            type
          }
        }
      `,
      variables: {
        id,
        patch
      }
    })

    if (response.errors) {
      console.error('update fail')
    } else {
      this.application = { ...this.application, ...response.data.updateApplication }
      console.log('update sucess')
    }
  }

  async deleteApplication(e) {
    e.preventDefault()

    const id = this.lifecycle.resourceId

    const response = await client.mutate({
      mutation: gql`
        mutation ($id: String!) {
          deleteApplication(id: $id)
        }
      `,
      variables: {
        id
      }
    })

    const result = response.data.deleteApplication
    if (result) {
      console.log('delete sucess')
      navigate('applications')
    } else {
      console.error('delete fail')
    }
  }
}
