import { componentName as descopeInternalComponentName } from './descope-phone-input-box-internal/PhoneFieldInternalInputBox';
import { forwardAttrs, getComponentName } from '../../../helpers/componentHelpers';
import { compose } from '../../../helpers';
import {
  createProxy,
  createStyleMixin,
  draggableMixin,
  inputOverrideValidConstraintsMixin,
  proxyInputMixin,
} from '../../../mixins';
import { TextFieldClass } from '../../descope-text-field/TextFieldClass';
import CountryCodes from '../CountryCodes';
import {
  resetInputLabelPosition,
  resetInputCursor,
  resetInputFieldDefaultWidth,
  resetInputFieldInvalidBackgroundColor,
  useHostExternalPadding,
  inputFloatingLabelStyle,
} from '../../../helpers/themeHelpers/resetHelpers';
import { syncAttrs } from '@descope-ui/common/components-helpers';

const textVars = TextFieldClass.cssVarList;

export const componentName = getComponentName('phone-input-box-field');

const customMixin = (superclass) =>
  class PhoneFieldInputBoxMixinClass extends superclass {
    static get CountryCodes() {
      return CountryCodes;
    }

    init() {
      super.init?.();

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

      template.innerHTML = `
				<${descopeInternalComponentName}
					tabindex="-1"
					slot="input"
				></${descopeInternalComponentName}>
      `;

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

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

      syncAttrs(this, this.inputElement, { includeAttrs: ['has-value'] });

      forwardAttrs(this.shadowRoot.host, this.inputElement, {
        includeAttrs: [
          'size',
          'minlength',
          'maxlength',
          'default-code',
          'disabled',
          'phone-input-placeholder',
          'label',
          'label-type',
          'allow-alphanumeric-input',
          'restrict-countries',
          'format-value',
          'strict-validation',
          'data-errormessage-type-mismatch',
        ],
      });
    }

    get phoneNumberInputEle() {
      return this.inputElement?.phoneNumberInputEle;
    }
  };

const {
  host,
  label,
  inputElement,
  requiredIndicator,
  inputField,
  internalComponent,
  internalComponentAfter,
  phoneInput,
  errorMessage,
  helperText,
} = {
  host: { selector: () => ':host' },
  label: { selector: '::part(label)' },
  placeholder: { selector: '> input:placeholder-shown' },
  inputElement: { selector: 'input' },
  requiredIndicator: { selector: '[required]::part(required-indicator)::after' },
  inputField: { selector: () => 'vaadin-text-field::part(input-field)' },
  internalComponent: {
    selector: 'descope-phone-field-internal-input-box',
  },
  internalComponentAfter: {
    selector: 'descope-phone-field-internal-input-box::after',
  },
  phoneInput: { selector: () => 'descope-text-field' },
  helperText: { selector: '::part(helper-text)' },
  errorMessage: { selector: '::part(error-message)' },
};

export const PhoneFieldInputBoxClass = compose(
  createStyleMixin({
    mappings: {
      fontSize: [
        host,
        inputField,
        {
          selector: TextFieldClass.componentName,
          property: TextFieldClass.cssVarList.fontSize,
        },
      ],
      fontFamily: [label, errorMessage, helperText],
      hostWidth: { ...host, property: 'width' },
      hostMinWidth: { ...host, property: 'min-width' },
      hostDirection: { ...host, property: 'direction' },

      inputHorizontalPadding: [
        { ...phoneInput, property: 'padding-left' },
        { ...phoneInput, property: 'padding-right' },
      ],

      labelFontSize: { ...label, property: 'font-size' },
      labelFontWeight: { ...label, property: 'font-weight' },
      labelTextColor: [
        { ...label, property: 'color' },
        { ...label, property: '-webkit-text-fill-color' },
        { ...requiredIndicator, property: 'color' },
      ],
      labelRequiredIndicator: { ...requiredIndicator, property: 'content' },
      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' },

      inputValueTextColor: { ...phoneInput, property: textVars.inputValueTextColor },

      inputPlaceholderTextColor: { ...phoneInput, property: textVars.inputPlaceholderColor },

      inputBorderStyle: { ...internalComponentAfter, property: 'border-style' },
      inputBorderWidth: { ...internalComponentAfter, property: 'border-width' },
      inputBorderColor: { ...internalComponentAfter, property: 'border-color' },
      inputBorderRadius: [
        { ...internalComponent, property: 'border-radius' },
        { ...internalComponentAfter, property: 'border-radius' },
      ],

      inputOutlineStyle: { ...internalComponent, property: 'outline-style' },
      inputOutlineColor: { ...internalComponent, property: 'outline-color' },
      inputOutlineWidth: { ...internalComponent, property: 'outline-width' },
      inputOutlineOffset: { ...internalComponent, property: 'outline-offset' },

      labelPosition: { ...label, property: 'position' },
      labelTopPosition: { ...label, property: 'top' },
      labelHorizontalPosition: [
        { ...label, property: 'left' },
        { ...label, property: 'right' },
      ],
      inputTransformY: { ...label, property: 'transform' },
      inputTransition: { ...label, property: 'transition' },
      marginInlineStart: { ...label, property: 'margin-inline-start' },
      valueInputHeight: { ...inputElement, property: 'height' },
      valueInputMarginBottom: {
        selector: TextFieldClass.componentName,
        property: textVars.valueInputMarginBottom,
      },
    },
  }),
  draggableMixin,
  inputOverrideValidConstraintsMixin,
  proxyInputMixin({ proxyProps: ['value', 'selectionStart'] }),
  customMixin
)(
  createProxy({
    slots: [],
    wrappedEleName: 'vaadin-text-field',
    style: () => `
    :host {
      display: inline-flex;
      max-width: 100%;
      box-sizing: border-box;
    }
    ${useHostExternalPadding(PhoneFieldInputBoxClass.cssVarList)}
    ${resetInputCursor('vaadin-text-field')}
    ${resetInputFieldInvalidBackgroundColor('vaadin-text-field')}
    ${resetInputFieldDefaultWidth()}

    vaadin-text-field {
      width: 100%;
      box-sizing: border-box;
      padding: 0;
    }
    vaadin-text-field[focus-ring]::part(input-field) {
      box-shadow: none;
    }
    vaadin-text-field::before {
      height: 0;
    }
    vaadin-text-field::part(input-field) {
      padding: 0;
      background: transparent;
      -webkit-mask-image: none;
    }
    descope-phone-field-internal-input-box {
      -webkit-mask-image: none;
      padding: 0;
      width: 100%;
    }
    descope-phone-field-internal-input-box > div {
      width: 100%;
    }
    descope-phone-field-internal-input-box descope-text-field {
      ${textVars.inputOutlineWidth}: 0;
      ${textVars.inputOutlineOffset}: 0;
    }
    descope-phone-field-internal-input-box::after {
      content: '';
      position: absolute;
      width: 100%;
      height: 100%;
      top: 0;
      left: 0;
      box-sizing: border-box;
      pointer-events: none;
    }
    descope-text-field {
      flex-grow: 1;
      width: 100%;
      direction: ltr;
    }
    vaadin-text-field[readonly] > input:placeholder-shown {
      opacity: 1;
    }
    vaadin-text-field::part(input-field)::after {
      border: none;
    }

    vaadin-text-field[label-type="floating"]:not([focused])[readonly] input:placeholder-shown {
      opacity: 0;
    }
    vaadin-text-field[label-type="floating"]:not([focused])[disabled] input:placeholder-shown {
      opacity: 0;
    }

    ${resetInputLabelPosition('vaadin-text-field')}
    ${inputFloatingLabelStyle()}
		`,
    excludeAttrsSync: ['tabindex', 'style'],
    componentName,
  })
);

export default PhoneFieldInputBoxClass;
