import { ComboBoxClass } from '@descope-ui/descope-combo-box/class';
import { componentName as descopeInternalComponentName } from './descope-phone-field-internal/PhoneFieldInternal';
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 {
  resetInputCursor,
  resetInputLabelPosition,
  resetInputFieldDefaultWidth,
  resetInputFieldInvalidBackgroundColor,
  useHostExternalPadding,
} from '../../../helpers/themeHelpers/resetHelpers';

const textVars = TextFieldClass.cssVarList;
const comboVars = ComboBoxClass.cssVarList;

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

const customMixin = (superclass) =>
  class PhoneFieldMixinClass 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);

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

    get countryCodeItems() {
      return this.inputElement?.countryCodeValue;
    }

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

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

    get countryCodes() {
      return Array.from(this.inputElement.countryCodeInputData).map((ele) =>
        ele.getAttribute('data-country-code')
      );
    }
  };

const {
  host,
  label,
  requiredIndicator,
  inputField,
  internalAfter,
  countryCodeInput,
  phoneInput,
  separator,
  errorMessage,
  helperText,
} = {
  host: { selector: () => ':host' },
  label: { selector: '::part(label)' },
  requiredIndicator: { selector: '[required]::part(required-indicator)::after' },
  inputField: { selector: '::part(input-field)' },
  internalAfter: { selector: 'descope-phone-field-internal::after' },
  phoneInput: { selector: () => 'descope-text-field' },
  countryCodeInput: { selector: () => 'descope-combo-box' },
  separator: { selector: 'descope-phone-field-internal .separator' },
  helperText: { selector: '::part(helper-text)' },
  errorMessage: { selector: '::part(error-message)' },
};

export const PhoneFieldClass = compose(
  createStyleMixin({
    mappings: {
      fontSize: [
        host,
        inputField,
        {
          selector: TextFieldClass.componentName,
          property: TextFieldClass.cssVarList.fontSize,
        },
        {
          selector: ComboBoxClass.componentName,
          property: ComboBoxClass.cssVarList.fontSize,
        },
      ],
      fontFamily: [
        label,
        errorMessage,
        helperText,
        {
          ...countryCodeInput,
          property: ComboBoxClass.cssVarList.overlay.fontFamily,
        },
      ],
      hostWidth: [
        { ...host, property: 'width' },
        { ...phoneInput, property: 'width' },
        { ...countryCodeInput, property: '--vaadin-combo-box-overlay-width' },
      ],
      hostDirection: { ...host, property: 'direction' },

      inputBorderStyle: [
        { ...internalAfter, property: 'border-style' },
        { ...separator, property: 'border-left-style' },
      ],
      inputBorderWidth: [
        { ...internalAfter, property: 'border-width' },
        { ...separator, property: 'border-left-width' },
      ],
      inputBorderColor: [
        { ...internalAfter, property: 'border-color' },
        { ...separator, property: 'border-left-color' },
      ],
      inputBorderRadius: [
        { ...inputField, property: 'border-radius' },
        { ...internalAfter, property: 'border-radius' },
      ],

      countryCodeInputWidth: { ...countryCodeInput, property: comboVars.hostWidth },
      countryCodeDropdownWidth: {
        ...countryCodeInput,
        property: '--vaadin-combo-box-overlay-width',
      },
      phoneInputWidth: { ...phoneInput, property: 'width' },

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

      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 },
        { ...countryCodeInput, property: comboVars.inputValueTextColor },
      ],

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

      overlayItemBackgroundColor: {
        selector: 'descope-combo-box',
        property: comboVars.overlayItemBackgroundColor,
      },

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

      valueInputHeight: [{ ...countryCodeInput, property: comboVars.valueInputHeight }],
      valueInputMarginBottom: [{ ...phoneInput, property: textVars.valueInputMarginBottom }],
      marginInlineStart: [
        { ...phoneInput, property: textVars.marginInlineStart },
        { ...countryCodeInput, property: comboVars.marginInlineStart },
      ],
    },
  }),
  draggableMixin,
  inputOverrideValidConstraintsMixin,
  proxyInputMixin({ proxyProps: ['value', 'selectionStart'] }),
  customMixin
)(
  createProxy({
    slots: [],
    wrappedEleName: 'vaadin-text-field',
    style: () => `
			:host {
				display: inline-flex;
				max-width: 100%;
				min-width: 15em;
				box-sizing: border-box;
			}
			${useHostExternalPadding(PhoneFieldClass.cssVarList)}
			${resetInputCursor('vaadin-text-field')}
			${resetInputFieldInvalidBackgroundColor('vaadin-text-field')}
			${resetInputFieldDefaultWidth()}

			div {
				display: inline-flex;
			}
			vaadin-text-field {
				width: 100%;
				height: 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(label) {
        margin-left: 0;
        margin-right: 0;
      }
			vaadin-text-field::part(input-field) {
				padding: 0;
				background: transparent;
				overflow: hidden;
			}
			descope-phone-field-internal {
				-webkit-mask-image: none;
				padding: 0;
				width: 100%;
				height: 100%;
        direction: ltr;
        position: relative;
			}
      descope-phone-field-internal::after {
        content: '';
        position: absolute;
        width: 100%;
        height: 100%;
        top: 0;
        left: 0;
        box-sizing: border-box;
        outline-offset: calc(var(${PhoneFieldClass.cssVarList.inputBorderWidth}) * -1);
        pointer-events: none;
      }
			descope-phone-field-internal > div {
				width: 100%;
				height: 100%;
			}
			descope-phone-field-internal .separator {
				flex: 0;
				border: none;
			}

			descope-combo-box {
				flex-shrink: 0;
        min-width: 5.75em;
				${comboVars.inputOutlineWidth}: 0;
				${comboVars.inputOutlineOffset}: 0;
				${comboVars.inputBorderWidth}: 0;
				${comboVars.inputBorderRadius}: 0;
			}
			descope-text-field {
				flex-grow: 1;
				${textVars.inputOutlineWidth}: 0;
				${textVars.inputOutlineOffset}: 0;
				${textVars.inputBorderWidth}: 0;
				${textVars.inputBorderRadius}: 0;
      }

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

			vaadin-text-field::part(input-field)::after {
				border: none;
			}
      ${resetInputLabelPosition('vaadin-text-field')}
		`,
    excludeAttrsSync: ['tabindex', 'style'],
    componentName,
  })
);

export default PhoneFieldClass;
