import { forwardAttrs, getComponentName } from '../../helpers/componentHelpers';
import { compose } from '../../helpers';
import { createStyleMixin, proxyInputMixin, draggableMixin, createProxy } from '../../mixins';
import { componentName as descopeInternalComponentName } from './descope-new-password-internal/componentName';
import { PasswordClass } from '../descope-password/PasswordClass';
import { useHostExternalPadding } from '../../helpers/themeHelpers/resetHelpers';
import { PolicyValidationClass } from '../descope-policy-validation/PolicyValidationClass';

export const componentName = getComponentName('new-password');

const policyPreviewVars = PolicyValidationClass.cssVarList;

const customMixin = (superclass) =>
  class NewPasswordMixinClass extends superclass {
    init() {
      super.init?.();

      const template = document.createElement('template');

      const externalInputAttr = this.getAttribute('external-input');

      template.innerHTML = `
			<${descopeInternalComponentName}
				name="new-password"
				tabindex="-1"
				slot="input"
        external-input="${externalInputAttr}"
			>
      </${descopeInternalComponentName}>
			`;

      this.baseElement.appendChild(template.content.cloneNode(true));

      this.inputElement = this.shadowRoot.querySelector(descopeInternalComponentName);

      if (this.getAttribute('external-input') === 'true') {
        this.initExternalInput();
      }

      forwardAttrs(this, this.inputElement, {
        includeAttrs: [
          'password-label',
          'password-placeholder',
          'confirm-label',
          'confirm-placeholder',
          'full-width',
          'size',
          'bordered',
          'label',
          'has-confirm',
          'invalid',
          'readonly',
          'disabled',
          'draggable',
          'has-validation',
          'policy-label',
          'active-policies',
          'available-policies',
          'data-password-policy-value-minlength',
          'data-password-policy-value-passwordstrength',
          'data-password-policy-value-disallowedchars',
          'data-password-policy-value-email',
          'label-type',
          'manual-visibility-toggle',
        ],
      });
    }

    createSlottedExternalInput(node, slotName) {
      const externalInput = node.querySelector('input');
      const slotEle = document.createElement('slot');

      const targetSlot = externalInput.getAttribute('slot');

      slotEle.setAttribute('name', slotName);
      slotEle.setAttribute('slot', targetSlot);

      node.appendChild(slotEle);

      // move external input
      externalInput.setAttribute('slot', slotName);
      externalInput.setAttribute('name', this.getAttribute('name'));
      externalInput.setAttribute('data-hidden-input', 'true');

      this.appendChild(externalInput);
    }

    initExternalInput() {
      // get descope input components
      this.passwordInput = this.inputElement.querySelector('[data-id="password"]');
      this.confirmInput = this.inputElement.querySelector('[data-id="confirm"]');

      // create slots for external password input
      this.createSlottedExternalInput(this.passwordInput, 'external-password-input');
      this.createSlottedExternalInput(this.confirmInput, 'external-confirm-input');
    }
  };

const {
  host,
  label,
  internalInputsWrapper,
  errorMessage,
  helperText,
  passwordInput,
  policyPreview,
} = {
  host: { selector: () => ':host' },
  label: { selector: '::part(label)' },
  internalInputsWrapper: { selector: 'descope-new-password-internal .wrapper' },
  helperText: { selector: '::part(helper-text)' },
  errorMessage: { selector: '::part(error-message)' },
  passwordInput: { selector: 'descope-password' },
  policyPreview: { selector: 'descope-policy-validation' },
};

export const NewPasswordClass = compose(
  createStyleMixin({
    mappings: {
      fontSize: [
        host,
        {},
        {
          selector: PasswordClass.componentName,
          property: PasswordClass.cssVarList.fontSize,
        },
      ],
      fontFamily: [label, errorMessage, helperText],
      labelFontSize: { ...label, property: 'font-size' },
      labelFontWeight: { ...label, property: 'font-weight' },
      inputValueFontWeight: {
        ...passwordInput,
        property: PasswordClass.cssVarList.inputValueFontWeight,
      },
      inputPlaceholderFontWeight: {
        ...passwordInput,
        property: PasswordClass.cssVarList.inputPlaceholderFontWeight,
      },
      helperTextFontWeight: { ...helperText, property: 'font-weight' },
      errorMessageFontWeight: { ...errorMessage, property: 'font-weight' },
      labelTextColor: { ...label, property: 'color' },
      errorMessageTextColor: { ...errorMessage, property: 'color' },
      errorMessageIcon: { ...errorMessage, property: 'background-image' },
      errorMessageIconSize: { ...errorMessage, property: 'background-size' },
      errorMessageIconPadding: { ...errorMessage, property: 'padding-inline-start' },
      errorMessageIconRepeat: { ...errorMessage, property: 'background-repeat' },
      errorMessageIconPosition: { ...errorMessage, property: 'background-position' },
      errorMessageFontSize: { ...errorMessage, property: 'font-size' },
      hostWidth: { ...host, property: 'width' },
      hostMinWidth: { ...host, property: 'min-width' },
      hostDirection: [
        { ...host, property: 'direction' },
        { ...passwordInput, property: PasswordClass.cssVarList.hostDirection },
      ],
      inputsRequiredIndicator: { ...host, property: 'content' },
      spaceBetweenInputs: { ...internalInputsWrapper, property: 'gap' },
      policyPreviewBackgroundColor: {
        ...policyPreview,
        property: policyPreviewVars.backgroundColor,
      },
      policyPreviewPadding: { ...policyPreview, property: policyPreviewVars.padding },

      valueInputHeight: { ...passwordInput, property: PasswordClass.cssVarList.valueInputHeight },
      valueInputMarginBottom: {
        ...passwordInput,
        property: PasswordClass.cssVarList.valueInputMarginBottom,
      },
    },
  }),
  draggableMixin,
  proxyInputMixin({ proxyProps: ['value', 'selectionStart'] }),
  customMixin
)(
  createProxy({
    slots: [],
    wrappedEleName: 'vaadin-text-field',
    style: () => `
		:host {
			display: inline-block;
			max-width: 100%;
			box-sizing: border-box;
		}
    :host ::part(error-message) {
      direction: ltr;
    }
		${useHostExternalPadding(PasswordClass.cssVarList)}
		vaadin-text-field {
			padding: 0;
			width: 100%;
			height: 100%;
		}
		vaadin-text-field::part(input-field) {
			min-height: 0;
			background: transparent;
			box-shadow: none;
			padding: 0;
		}
		vaadin-text-field::part(input-field)::after {
			background: transparent;
			opacity: 0;
		}
		descope-new-password-internal {
			-webkit-mask-image: none;
			min-height: 0;
			width: 100%;
			padding: 0;
		}
		descope-new-password-internal > .wrapper {
      -webkit-mask-image: none;
			width: 100%;
			height: 100%;
			display: flex;
			flex-direction: column;
		}
		descope-password {
			display: block;
			width: 100%;
		}
		descope-new-password-internal vaadin-password-field::before {
			height: initial;
		}
    descope-policy-validation {
      margin-top: 8px;
      display: flex;
    }
    .hidden {
      display: none;
    }
		`,
    excludeAttrsSync: ['tabindex', 'style'],
    componentName,
  })
);
