import { DataSourceEditor, removeState, setState, toExpression } from '@silexlabs/grapesjs-data-source'
import { ClientConfig } from '@silexlabs/silex/src/ts/client/config'
//import { ClientEvent } from '@silexlabs/silex/src/ts/client/events'
import { EleventyPluginOptions, Silex11tyPluginWebsiteSettings } from '../client'
import { html, TemplateResult } from 'lit-html'
import { Page } from 'grapesjs'
import { WebsiteSettings } from '@silexlabs/silex/src/ts/types'

/**
 * Main function to add the settings to the page
 */
export default function(config: ClientConfig, opts: EleventyPluginOptions): void {
  if(!opts.enable11ty) return // Do not add the settings if 11ty is disabled
  config.on('silex:startup:end', () => {
    const editor = config.getEditor() as DataSourceEditor
    editor.on(/* ClientEvent.SETT(INGS_SAVE_START */'silex:settings:save:start', (page: Page) => updateBodyStates(editor, page))
    config.addSettings({
      id: 'cms',
      label: 'CMS',
      render: (settings: WebsiteSettings, page: Backbone.Model) => render(settings, config, page as unknown as Page), // FIXME: make sure Page is a Backbone.Model
    }, 'page')
  })
}

/**
 * Set the state on the body component
 * This is only useful to build the GraphQL query
 */
function stateOnBody(editor, value, name, body) {
  if (value) {
    const expression = toExpression(value)
    if(expression) {
      setState(body, name, {
        label: name,
        hidden: true,
        expression,
      })
    } else {
      console.error(`Invalid JSON for ${name}`)
      removeState(body, name)
      editor.runCommand('notifications:add', {
        type: 'error',
        message: `Invalid JSON for ${name}`,
        group: 'Errors in your settings',
      })
    }
  } else {
    removeState(body, name)
  }
}

function showWarningDirty() {
  document.getElementById('pageination-data-changed')?.classList.remove('silex-hidden')
}

function hideWarningDirty() {
  document.getElementById('pageination-data-changed')?.classList.add('silex-hidden')
}

/**
 * Set the state on the body component
 * This is only useful to build the GraphQL query
 */
function updateBodyStates(editor: DataSourceEditor, page: Page) {
  hideWarningDirty()
  if (page) {
    const settings = page?.get('settings') as Silex11tyPluginWebsiteSettings | undefined
    if (settings) {
      const body = page.getMainComponent()
      stateOnBody(editor, settings.eleventySeoTitle, 'eleventySeoTitle', body)
      stateOnBody(editor, settings.eleventySeoDescription, 'eleventySeoDescription', body)
      stateOnBody(editor, settings.eleventyFavicon, 'eleventyFavicon', body)
      stateOnBody(editor, settings.eleventyOGImage, 'eleventyOGImage', body)
      stateOnBody(editor, settings.eleventyOGTitle, 'eleventyOGTitle', body)
      stateOnBody(editor, settings.eleventyOGDescription, 'eleventyOGDescription', body)
      stateOnBody(editor, settings.eleventyPageData, 'eleventyPageData', body)
      stateOnBody(editor, settings.eleventyPermalink, 'eleventyPermalink', body)
    }
  }
}

/**
 * Render the settings form
 */
function render(settings: Silex11tyPluginWebsiteSettings, config: ClientConfig, page: Page): TemplateResult {
  setTimeout(() => {
    // Update the settings form when the selection changed without recreating the form
    (document.querySelectorAll('#settings-cms input') as NodeListOf<HTMLInputElement>)
      .forEach((input: HTMLInputElement) => {
        switch (input.type) {
        case 'checkbox':
          input.checked = !!settings[input.name]
          break
        default:
          input.value = settings[input.name] ?? ''
        }
      })
  })
  const body = page.getMainComponent()
  return html`
    <style>
      .silex-warning {
        margin-top: 10px;
        padding: 10px;
        background-color: var(--ds-primary);
        border-color: var(--ds-button-color);
        color: #721c24;
        border: 1px solid transparent;
        border-radius: .25rem;
      }
    </style>
    <div id="settings-cms" class="silex-hideable silex-hidden">
      <div class="gjs-sm-sector-title">Silex CMS - Page settings</div>
      <div class="silex-help">
        The "Silex CMS" feature integrates <a target="_blank" href="https://www.11ty.dev/">11ty</a> static site generator and your favorite headless CMS with Silex.
        <br>Read the <a target="_blank" href="https://docs.silex.me/en/user/cms">documentation</a> to learn more.
      </div>
      <div class="silex-form__group col2">
        <label class="silex-form__element">
          <h3>Create pages from data</h3>
          <p class="silex-help">Pagination allows you to iterate over data and create multiple webiste pages from a single page in Silex. </p>
          <state-editor
            id="eleventyPageData"
            name="eleventyPageData"
            value=${settings.eleventyPageData ?? ''}
            .editor=${config.getEditor()}
            .selected=${body}
            @change=${() => {
    showWarningDirty()
  }}
            no-states
            no-filters
          >
            <label slot="label">Data</label>
          </state-editor>
          <div
            id="pageination-data-changed"
            class="silex-warning silex-hidden"
            >
            <!-- Reloading silex will make it possible to set the permalink with the latest available data -->
            <p>\u26A0\uFE0F Pagination data changed. Please click "<strong>apply</strong>" then <strong>reload</strong> Silex.</p>
          </div>
          <label class="silex-form__element">Size
            <input type="number" name="eleventyPageSize" .value=${settings.eleventyPageSize ?? 1}/>
          </label>
          <label class="silex-form__element">Reverse
            <input type="checkbox" name="eleventyPageReverse" ?checked=${!!settings.eleventyPageReverse}/>
          </label>
          <state-editor
            id="eleventyPermalink"
            name="eleventyPermalink"
            value=${settings.eleventyPermalink ?? ''}
            .editor=${config.getEditor()}
            .selected=${body}
          >
            <label slot="label">Permalink</label>
          </state-editor>
          <label class="silex-form__element">Available languages
            <p class="silex-help">Silex can duplicate this page for each language and generate a different URL for each language.</p>
            <p class="silex-help">Provide a comma separated list of languages. For example: <code>en,fr</code>. An empty value will deactivate this feature.</p>
            <input type="text" name="silexLanguagesList" .value=${settings.silexLanguagesList ?? ''}/>
          </label>
        </label>
        <label class="silex-form__element">
          <h3>Navigation Plugin</h3>
          <p class="silex-help">This 11ty plugin enables infinite-depth hierarchical navigation in Eleventy projects. Supports breadcrumbs too! <a target="_blank" href="https://www.11ty.dev/docs/plugins/navigation/">Read more about the Navigation Plugin</a>.</p>
          <label class="silex-form__element">Key
            <input type="text" name="eleventyNavigationKey" .value=${settings.eleventyNavigationKey ?? ''}/>
          </label>
          <label class="silex-form__element">Title
            <input type="text" name="eleventyNavigationTitle" .value=${settings.eleventyNavigationTitle ?? ''}/>
          </label>
          <label class="silex-form__element">Order
            <input type="number" name="eleventyNavigationOrder" .value=${settings.eleventyNavigationOrder ?? ''}/>
          </label>
          <label class="silex-form__element">Parent
            <input type="text" name="eleventyNavigationParent" .value=${settings.eleventyNavigationParent ?? ''}/>
          </label>
          <label class="silex-form__element">URL
            <input type="text" name="eleventyNavigationUrl" .value=${settings.eleventyNavigationUrl ?? ''}/>
          </label>
        </label>
        <label class="silex-form__element">
          <h3>SEO</h3>
          <state-editor
            id="eleventySeoTitle"
            name="eleventySeoTitle"
            .value=${settings.eleventySeoTitle ?? ''}
            .editor=${config.getEditor()}
            .selected=${body}
          >
            <label slot="label">Title</label>
          </state-editor>
          <state-editor
            id="eleventySeoDescription"
            name="eleventySeoDescription"
            .value=${settings.eleventySeoDescription ?? ''}
            .editor=${config.getEditor()}
            .selected=${body}
          >
            <label slot="label">Description</label>
          </state-editor>
          <state-editor
            id="eleventyFavicon"
            name="eleventyFavicon"
            .value=${settings.eleventyFavicon ?? ''}
            .editor=${config.getEditor()}
            .selected=${body}
          >
            <label slot="label">Favicon</label>
          </state-editor>
        </label>
        <label class="silex-form__element">
          <h3>Social</h3>
          <state-editor
            id="eleventyOGImage"
            name="eleventyOGImage"
            .value=${settings.eleventyOGImage ?? ''}
            .editor=${config.getEditor()}
            .selected=${body}
          >
            <label slot="label">OG Image</label>
          </state-editor>
          <state-editor
            id="eleventyOGTitle"
            name="eleventyOGTitle"
            .value=${settings.eleventyOGTitle ?? ''}
            .editor=${config.getEditor()}
            .selected=${body}
          >
            <label slot="label">OG Title</label>
          </state-editor>
          <state-editor
            id="eleventyOGDescription"
            name="eleventyOGDescription"
            .value=${settings.eleventyOGDescription ?? ''}
            .editor=${config.getEditor()}
            .selected=${body}
          >
            <label slot="label">OG Description</label>
          </state-editor>
      </div>
    </div>
    `
}
