import { Component } from 'react'
import { backgroundStyle, borderStyles, borderPosition } from '@adalo/constants'

// utils
import { getShadowStyles } from 'utils/styles'
import { handleFontSize } from 'utils/type'

// types
import { IApp, IAttributes, IObject } from 'interfaces'
import { Optional } from 'types'

export interface BaseObjectProps extends Component {
  app: IApp
  object: IObject
  bindingData?: object
  isResponsiveComponent: boolean
  nodeHeight: number
}

export default class BaseObject<
  T extends BaseObjectProps
> extends Component<T> {
  getBorderOffset() {
    const {
      object: { attributes },
    } = this.props

    if (attributes.borderStyle === borderStyles.NONE) {
      return 0
    }

    if (attributes.borderPosition && attributes.borderWidth) {
      switch (attributes.borderPosition) {
        case borderPosition.CENTER:
          return -0.5 * attributes.borderWidth
        case borderPosition.OUTSIDE:
          return -1 * attributes.borderWidth
      }
    }

    return 0
  }

  getBorderRadius(
    prop = 'borderRadius' as keyof IAttributes,
    isBackground = false
  ): Optional<number> {
    const {
      object: { attributes },
    } = this.props
    let { width, height, borderStyle, borderWidth } = attributes

    let borderRadius = ((prop: keyof IAttributes) =>
      typeof attributes[prop] !== 'undefined'
        ? attributes[prop]
        : attributes.borderRadius)(prop)

    if (typeof borderRadius !== 'number') {
      return attributes?.borderRadius ?? undefined
    }

    if (borderRadius <= 0) {
      return 0
    }

    if (!width) {
      width = height
    }

    if (!height) {
      return borderRadius || 0
    }

    borderRadius = borderRadius || 0
    borderRadius = Math.min(borderRadius, width / 2, height / 2)

    if (borderStyle !== borderStyles.NONE && borderWidth && borderWidth > 0) {
      const offset = borderWidth / 2

      borderRadius = isBackground
        ? borderRadius - offset
        : borderRadius + offset
    }

    return borderRadius
  }

  getBorderRadiusNew(isBackground = false): {
    borderRadius: Optional<number>
    borderTopLeftRadius: Optional<number>
    borderTopRightRadius: Optional<number>
    borderBottomLeftRadius: Optional<number>
    borderBottomRightRadius: Optional<number>
  } {
    return {
      borderRadius: this.getBorderRadius('borderRadius', isBackground),
      borderTopLeftRadius: this.getBorderRadius('borderTopLeftRadius', isBackground), // prettier-ignore
      borderTopRightRadius: this.getBorderRadius('borderTopRightRadius', isBackground), // prettier-ignore
      borderBottomLeftRadius: this.getBorderRadius('borderBottomLeftRadius', isBackground), // prettier-ignore
      borderBottomRightRadius: this.getBorderRadius('borderBottomRightRadius', isBackground), // prettier-ignore
    }
  }

  borderStyles() {
    const { object } = this.props
    const { attributes } = object
    const radiusStyles = this.getBorderRadiusNew()

    if (attributes.borderStyle === borderStyles.NONE) {
      return {
        ...radiusStyles,
        borderStyle: undefined,
        borderWidth: 0,
      }
    }

    return {
      ...radiusStyles,
      borderStyle: attributes.borderStyle,
      borderWidth: attributes.borderWidth,
      borderColor: attributes.borderColor,
    }
  }

  shadowStyles() {
    const { object } = this.props
    const { shadow } = object.attributes

    return getShadowStyles(shadow)
  }

  backgroundStyles() {
    const { object } = this.props
    const { attributes } = object

    if (attributes?.backgroundStyle !== backgroundStyle.COLOR) {
      return {
        backgroundColor: 'transparent',
      }
    }

    return {
      backgroundColor: attributes.backgroundColor,
    }
  }

  textStyles() {
    const { object } = this.props
    const { attributes } = object

    return {
      color: attributes.color,
      fontSize: handleFontSize(attributes.fontSize),
      fontWeight: attributes.fontWeight,
      textAlign: attributes.textAlignment,
      fontFamily: attributes.fontFamily,
    }
  }

  getDataBindingOfType(bindingType?: string) {
    const { object, bindingData } = this.props
    const binding = object.dataBinding

    if (binding && binding.bindingType === bindingType) {
      return { binding, data: bindingData }
    }
  }

  getDataBindingsOfType(bindingType?: string) {
    const binding = this.getDataBindingOfType(bindingType)

    return binding ? [binding] : []
  }

  getOpacity = () => {
    const {
      object: { attributes },
    } = this.props

    return attributes?.opacity || attributes?.opacity === 0
      ? { opacity: attributes.opacity }
      : {}
  }
}
