import * as plugins from './00plugins.js';
import * as colors from './00colors.js';

import {
  DeesElement,
  customElement,
  html,
  css,
  unsafeCSS,
  type CSSResult,
  cssManager,
  property,
  type TemplateResult,
} from '@design.estate/dees-element';

import * as domtools from '@design.estate/dees-domtools';

export interface IStep {
  title: string;
  content: TemplateResult;
  validationFunc?: (stepper: DeesStepper, htmlElement: HTMLElement) => Promise<any>;
  onReturnToStepFunc?: (stepper: DeesStepper, htmlElement: HTMLElement) => Promise<any>;
  validationFuncCalled?: boolean;
}

declare global {
  interface HTMLElementTagNameMap {
    'dees-stepper': DeesStepper;
  }
}

@customElement('dees-stepper')
export class DeesStepper extends DeesElement {
  public static demo = () =>
    html`
      <dees-stepper
        .steps=${[
          {
            title: 'Whats your name?',
            content: html`
              <dees-form>
                <dees-input-text
                  key="email"
                  label="Your Email"
                  value="hello@something.com"
                  disabled
                ></dees-input-text>
                <dees-input-text key="firstName" required label="Vorname"></dees-input-text>
                <dees-input-text key="lastName" required label="Nachname"></dees-input-text>
                <dees-form-submit>Next</dees-form-submit>
              </dees-form>
            `,
            validationFunc: async (stepperArg, elementArg) => {
              const deesForm = elementArg.querySelector('dees-form');
              deesForm.addEventListener('formData', (eventArg) => {
                stepperArg.goNext();
              });
            },
          },
          {
            title: 'Whats your mobile number?',
            content: html``,
          },
        ] as IStep[]}
      ></dees-stepper>
    `;

  @property({
    type: Array,
  })
  public steps: IStep[] = [];

  @property({
    type: Object,
  })
  public selectedStep: IStep;

  constructor() {
    super();
  }

  public static styles = [
    cssManager.defaultStyles,
    css`
      :host {
        position: absolute;
        width: 100%;
        height: 100%;
      }
      .stepperContainer {
        position: absolute;
        width: 100%;
        height: 100%;
        background: ${cssManager.bdTheme('#eeeeeb', '#000')};
        overflow: hidden;
      }

      .step {
        position: relative;
        pointer-events: none;
        overflow: hidden;
        transition: all 0.7s ease-in-out;
        max-width: 500px;
        min-height: 300px;
        border-radius: 16px;
        background: ${cssManager.bdTheme('#ffffff', '#181818')};
        border-top: 1px solid ${cssManager.bdTheme('#ffffff', '#181818')};
        color: ${cssManager.bdTheme('#333', '#fff')};
        margin: auto;
        margin-bottom: 20px;
        filter: opacity(0.5) grayscale(1);
        box-shadow: 0px 0px 3px #00000010;
        user-select: none;
      }

      .step.selected {
        border-top: 1px solid #e4002b;
        pointer-events: all;
        filter: opacity(1) grayscale(0);
        box-shadow: 0px 0px 5px #00000010;
        user-select: auto;
      }

      .step.hiddenStep {
        filter: opacity(0);
      }

      .step:last-child {
        margin-bottom: 100vh;
      }

      .step .stepCounter {
        color: #999;
        position: absolute;
        top: 0px;
        right: 0px;
        padding: 10px 15px;
        font-size: 12px;
        border-bottom-left-radius: 3px;
        background: ${cssManager.bdTheme('#00000008', '#ffffff08')};
      }

      .step .goBack {
        color: #999;
        cursor: default;
        position: absolute;
        top: 0px;
        left: 0px;
        padding: 10px 15px;
        font-size: 12px;
        border-bottom-right-radius: 3px;
        background: ${cssManager.bdTheme('#00000008', '#ffffff08')};
      }

      .step .goBack:hover {
        color: ${cssManager.bdTheme('#333', '#fff')};
        background: ${cssManager.bdTheme('#00000012', colors.dark.blue)};
      }

      .step .goBack:active {
        color: ${cssManager.bdTheme('#333', '#fff')};
        background: ${cssManager.bdTheme('#00000012', colors.dark.blueActive)};
      }

      .step .goBack span {
        transition: all 0.2s;
        display: inline-block;
      }

      .step .goBack:hover span {
        transform: translateX(-2px);
      }

      .step .title {
        text-align: center;
        padding-top: 50px;
        font-family: 'Geist Sans', sans-serif;
        font-size: 22px;

        font-weight: 500;
      }

      .step .content {
        padding: 20px;
      }
    `,
  ];

  public render() {
    return html`
      <div class="stepperContainer">
        ${this.steps.map(
          (stepArg) =>
            html`<div
              class="step ${stepArg === this.selectedStep
                ? 'selected'
                : null} ${this.getIndexOfStep(stepArg) > this.getIndexOfStep(this.selectedStep)
                ? 'hiddenStep'
                : ''}"
            >
              ${this.getIndexOfStep(stepArg) > 0
                ? html`<div class="goBack" @click=${this.goBack}><span style="font-family: Inter"><-</span> go to previous step</div>`
                : ``}
              <div class="stepCounter">
                Step ${this.steps.findIndex((elementArg) => elementArg === stepArg) + 1} of
                ${this.steps.length}
              </div>
              <div class="title">${stepArg.title}</div>
              <div class="content">${stepArg.content}</div>
            </div> `
        )}
      </div>
    `;
  }

  public getIndexOfStep = (stepArg: IStep): number => {
    return this.steps.findIndex((stepArg2) => stepArg === stepArg2);
  };

  public async firstUpdated() {
    await this.domtoolsPromise;
    await this.domtools.convenience.smartdelay.delayFor(0);
    this.selectedStep = this.steps[0];
    this.setScrollStatus();
  }

  public async updated() {
    this.setScrollStatus();
  }

  public scroller: typeof domtools.plugins.SweetScroll.prototype;

  public async setScrollStatus() {
    const stepperContainer: HTMLElement = this.shadowRoot.querySelector('.stepperContainer');
    const firstStepElement: HTMLElement = this.shadowRoot.querySelector('.step');
    const selectedStepElement: HTMLElement = this.shadowRoot.querySelector('.selected');
    if (!selectedStepElement) {
      return;
    }
    if (!stepperContainer.style.paddingTop) {
      stepperContainer.style.paddingTop = `${
        stepperContainer.offsetHeight / 2 - selectedStepElement.offsetHeight / 2
      }px`;
    }
    console.log('Setting scroll status');
    console.log(selectedStepElement);
    const scrollPosition =
      selectedStepElement.offsetTop -
      stepperContainer.offsetHeight / 2 +
      selectedStepElement.offsetHeight / 2;
    console.log(scrollPosition);
    const domtoolsInstance = await domtools.DomTools.setupDomTools();
    if (!this.scroller) {
      this.scroller = new domtools.plugins.SweetScroll(
        {
          vertical: true,
          horizontal: false,
          easing: 'easeInOutExpo',
          duration: 700,
        },
        stepperContainer
      );
    }
    if (!this.selectedStep.validationFuncCalled && this.selectedStep.validationFunc) {
      this.selectedStep.validationFuncCalled = true;
      await this.selectedStep.validationFunc(this, selectedStepElement);
    }
    this.scroller.to(scrollPosition);
  }

  public async goBack() {
    const currentIndex = this.steps.findIndex((stepArg) => stepArg === this.selectedStep);
    this.selectedStep = this.steps[currentIndex - 1];
    await this.domtoolsPromise;
    await this.domtools.convenience.smartdelay.delayFor(100);
    this.selectedStep.onReturnToStepFunc?.(this, this.shadowRoot.querySelector('.selected'));
  }

  public goNext() {
    const currentIndex = this.steps.findIndex((stepArg) => stepArg === this.selectedStep);
    this.selectedStep = this.steps[currentIndex + 1];
  }
}