import React, { useEffect } from 'react'
import { Button, Icon, Dropdown, SelectorArrow } from '$core-components'
import UEditProvider from './ueditProvider'
import { AdorDropDown } from './AdorDropDown'
import { UEditContentObject } from '@ustore/uedit'
import { UStoreProvider } from '@ustore/core'
import Hashids from 'hashids'
import { t } from '$themelocalization'
import features from '$features'
import EditorTooltip from './EditorTooltip'
import './ImageControlsSection.scss'
import ShapeControlsSection from './ShapeControlsSection'

const percentList = [25, 50, 75, 90, 100, 110, 125, 150, 175, 200].map(i => ({ name: `${i}%`, value: i }))

function findClosest (numbers, target) {
  return numbers.reduce((closest, num) =>
    Math.abs(num - target) < Math.abs(closest - target) ? num : closest
  )
}

const withCustomProps = (WrappedComponent = {}) => {
  return (props) => {
    const regex = new RegExp(/[!$%^&*()+|~=`{}[\]:";'<>?,./]/, 'g')
    const id = props.id ? props.id.replace('root_', '').replace(regex, '') : 'null'
    const hashids = new Hashids(id)
    const hashedID = hashids.encode(1, 2, 3)

    const onDucChange = (value, errors = [], skipValidation = false) => {
      value = value || '__xmpie_error__'
      const newDucValue =  value === 'default' ? undefined : value
      const schemaErrors = !value && props.uiSchema['ui:errorMessages']
        ? Object.values(props.uiSchema['ui:errorMessages']).map((err) => err)
        : []
      const errSchema = { [props.id]: { __errors: [...schemaErrors, ...errors] } }
      props.onChange(props.id || value, newDucValue === '__xmpie__clear__' ? '' : newDucValue, errSchema, skipValidation)
    }

    return (
      <div className={`a${hashedID}`}>
        <WrappedComponent
          {...props}
          id={id}
          disabled={props.readonly}
          onChange={onDucChange}
        />
      </div>
    )
  }

}

const widgets = window.uStoreDucs.reduce((r, duc) => ({ ...r, [duc.name]: withCustomProps(duc.component) }), {})
const WidgetComponent = widgets['gallerySelector']

const imageSelectorDefaultAssetProperty = {
  propertySchema: {
    custom: {
      validation: []
    }
  },
  uiSchema: {
    'ui:readonly': false,
    'ui:options': {
      custom: {
        allowedExtensions: ['JPG', 'JPEG', 'TIFF', 'TIF', 'PDF', 'PNG'],
        allowUpload: true,
        libraryAssetsAllowEditing: true,
      },
    }
  },
  required: false,
}

const ImageControlsSection = ({
  uEditDisplayContentObjectList,
  properties,
  ueditSelectedBoxId,
  locks,
  onChange
}) => {
  const items = Object.entries(UEditProvider.getOriginalMaterials().ImageResources)
    .filter((e => e[0].match(/.*\.(png|jpg|jpeg|gif|bmp)$/)))
    .map(([name, value]) => ({ name, value }))
  const [width, setWidth] = React.useState(percentList.find(i => i.value === 100))
  const [height, setHeight] = React.useState(percentList.find(i => i.value === 100))
  const [linked, setLinked] = React.useState(false)
  const [widthSelectedText, setWidthSelectedText] = React.useState(null)
  const [heightSelectedText, setHeightSelectedText] = React.useState(null)
  const [selectedImage, setSelectedImage] = React.useState(null)
  const [selectedAdor, setSelectedAdor] = React.useState('')
  const [selectionProps, setSelectionProps] = React.useState(null)
  const [errors, setErrors] = React.useState([])

  const defaultAssets =
    UEditProvider.getOriginalMaterials().ImageResources.filter(({Key}) => !/(^Assets\/)|(indx_.*)|\.eps$/i.test(Key)).map(item => ({
      AssetID: item.Key,
      DisplayName: item.DisplayName,
      FileName: item.DisplayName,
      IsUploaded: false,
      isUeditAsset: true,
      ModificationDate: new Date().toDateString(),
      ThumbnailUrl: item.Url
    }))

  useEffect(() => {
    UEditProvider.uEdit.getDocumentView().selection[0]?.imageContent?.listen('imageScaleTransform_propertyChanged.imagescaleTracking', (e) => {
      const imageScaleTransform = UEditProvider.uEdit.getDocumentView().selection[0]?.imageContent?.imageScaleTransform
      if (imageScaleTransform) {
        const wScaleValue = imageScaleTransform ? Math.round(imageScaleTransform[0] * 100) : 100
        const hScaleValue = imageScaleTransform ? Math.round(imageScaleTransform[3] * 100) : 100
        const correctedWidth = wScaleValue && findClosest(percentList.map(e => e.value), wScaleValue)
        const correctedHeight = findClosest(percentList.map(e => e.value), hScaleValue)

        setWidth(percentList.find(e => e.value === correctedWidth) || null)
        setHeight(percentList.find(e => e.value === correctedHeight) || null)
        setWidthSelectedText(`${correctedWidth}%`)
        setHeightSelectedText(`${correctedHeight}%`)
      }

      window.queueMicrotask(() => {
        UEditProvider.refreshFitImage()
      })
    })

    const image = items.find(i => i.name === UEditProvider.uEdit.getDocumentView().selection[0]?.imageContent?.imageURLSource)
    setSelectedImage(image)

    return () => {
      UEditProvider.uEdit.getDocumentView().selection[0].imageContent?.unlisten('imageScaleTransform_propertyChanged.imagescaleTracking')
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])

  useEffect(() => {
    const adorName = UEditProvider.getBoxSelection().imageContent?.adorName || ''
    const imageURLSource = UEditProvider.getBoxSelection().imageContent?.imageURLSource || ''
    setErrors([])

    if (adorName) {
      UEditProvider.setImageAdor(adorName)
      setSelectedAdor(adorName)
      setSelectionProps(Object.values(properties).find(p => p.custom.code === adorName))
      setSelectedImage(null)
    } else if (imageURLSource) {
      setSelectedImage(defaultAssets.find(i => i.AssetID === imageURLSource) || {
        AssetID: imageURLSource
      })
    } else {
      setSelectionProps(null)
      setSelectedImage(null)
      setSelectedAdor('')
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [ueditSelectedBoxId, properties])

  const onWidthChange = (item) => {
    UEditProvider.uEdit.getDocumentView().selection[0].width *= item.value / 100
    if (linked) {
      UEditProvider.uEdit.getDocumentView().selection[0].height *= item.value / 100
    }
    UEditProvider.refreshFitImage()
  }

  const onHeightChange = (item) => {
    UEditProvider.uEdit.getDocumentView().selection[0].height *= item.value / 100
    if (linked) {
      UEditProvider.uEdit.getDocumentView().selection[0].width *= item.value / 100
    }
    UEditProvider.refreshFitImage()
  }

  const onGalleryChange = async (assetId, propValue, errs) => {
    if (propValue === '') {
      UEditProvider.setImage({ name: null })
      setSelectedImage(null)
      setSelectedAdor('')
      return
    }

    const selectionErrors = errs ? Object.values(errs).flatMap(v => v.__errors) : []
    if (selectionErrors.length > 0) {
      setErrors(selectionErrors)
      return
    }
    setErrors([])
    const image =  await window.UStoreProvider.state.assets.getAsset(propValue.replace('Assets/', ''))
    setSelectedImage(image)
    UEditProvider.setImageAction({ ...image, AssetID: `Assets/${propValue}` })
    if (selectionProps) {
      onChange(selectionProps.id, propValue, errors)
    }
  }

  return <div className="image-section">
    {uEditDisplayContentObjectList && (!locks.ADD_AND_REMOVE_CONTENT_OBJECTS_LOCKED && !locks.REPLACE_CONTENT_LOCKED) &&
      <div className="ador-list">
        <AdorDropDown filterBy={opt => opt.type === UEditContentObject.eTypeImage}
                      onChange={(value) => {
                        setSelectionProps(Object.values(properties).find(p => p.custom.code === value.name))
                        UEditProvider.setImageAdor(value.value)
                        setSelectedAdor(value.value)
                        setSelectedImage(null)
                      }}
                      selectedValue={selectedAdor}/>
      </div>}
    <div className="image-controls-row image-gallery-duc">
      {!locks.REPLACE_CONTENT_LOCKED && <WidgetComponent
        features={features}
        formContext={{ UStoreProvider, defaultAssets, noProps: true }}
        id={selectionProps?.custom?.id || ''}
        onChange={onGalleryChange}
        onBlur={() => {}}
        options={(selectionProps || imageSelectorDefaultAssetProperty).uiSchema['ui:options']}
        readonly={(selectionProps || imageSelectorDefaultAssetProperty).uiSchema['ui:readonly']}
        required={(selectionProps || imageSelectorDefaultAssetProperty).required}
        schema={(selectionProps || imageSelectorDefaultAssetProperty).propertySchema}
        t={t}
        uiSchema={(selectionProps || imageSelectorDefaultAssetProperty).uiSchema}
        value={selectionProps?.value || selectedImage?.AssetID?.replace('Assets/', '') || ''}
      />}
      {errors.length > 0 && <div>{errors.map((error, idx) => (
        <div className="duc-error" key={idx}>
          <div className="error-text">{error}</div>
        </div>
      ))}</div>}
    </div>

    <div className="image-controls-row">
      <div className="width-height-controls">
        <div className="image-controls-row">
          <label>{t('UEdit.ImageControlSection.Width')}</label>
          <Dropdown customArrow={<SelectorArrow/>} items={percentList} selectedValue={width} onChange={onWidthChange}
                    selectedText={widthSelectedText}/>
        </div>
        <div className="image-controls-row">
          <label>{t('UEdit.ImageControlSection.Height')}</label>
          <Dropdown customArrow={<SelectorArrow/>} items={percentList} selectedValue={height} onChange={onHeightChange}
                    selectedText={heightSelectedText}/>
        </div>
      </div>
      <div className="lock-aspect-ratio">
        <Button onClick={() => setLinked(!linked)}>
          {!linked ? <Icon name="uedit-unlink.svg" width="24px" height="24px"/> :
            <Icon name="uedit-link.svg" width="32px" height="52px"/>}
          {linked ? <EditorTooltip width={200} text={`${t('UEdit.Locked')}`}/> :
              <EditorTooltip width={200} text={`${t('UEdit.Unlocked')}`}/>}
        </Button>
      </div>
    </div>
    <div className="image-controls-row">
      <label>{t('UEdit.ImageControlSection.Fitting')}</label>
      <Button onClick={() => UEditProvider.fitImage(false)} className="btn-fitting">
        <Icon name="uedit-fit-image.svg" width="50px" height="50px"/>
        <EditorTooltip width={120} text={`${t('UEdit.FitImage')}`}/>
      </Button>
    </div>
    <div className="horizontal-line"/>
    <ShapeControlsSection ueditSelectedBoxId={ueditSelectedBoxId}/>
  </div>

}

export default React.memo(ImageControlsSection)
