import React, { useRef, useState, useEffect } from 'react'
import './styles.scss'
import { OffsetAnnotation } from './offsetAnnotation'
import { AnnotationLayerTypes } from './types'

/**
 * Displays an SVG with the provided annotations above an wrapper or svg.
 *
 */

export const AnnotationLayer = ({
  id,
  annotations,
  AnnotationComponent,
  lineHeight = 17,
  linePadding = 2,
  hideMarker = false,
  locator = false,
  lineFlow = 'flows',
  marker = ['none', 'dot'],
  children
}: AnnotationLayerTypes) => {
  const wrapper = useRef<HTMLImageElement>(null)
  const svg = useRef<SVGSVGElement>(null)
  const [loaded, setLoaded] = useState<boolean>(false)
  const [svgSize, setSvgSize] = useState<[number, number]>([0, 0])
  const [locatorPos, setLocatorPos] = useState<[number, number]>([0, 0])
  const [locatorValue, setLocatorValue] = useState<string | undefined>(
    undefined
  )
  const [viewBox, setviewBox] = useState('0 0 0 0')

  // steps for grid values
  const gridValues = [10, 20, 30, 40, 50, 60, 70, 80, 90]

  // function to change height of the content
  const changeHeight = (wrapper: React.RefObject<HTMLElement>) => {
    if (wrapper && wrapper.current) {
      if (wrapper.current.clientHeight > 0) {
        setSvgSize([
          wrapper.current.clientWidth || 0,
          wrapper.current.clientHeight || 0
        ])
        setviewBox(
          '0 0 ' +
            wrapper.current.clientWidth +
            ' ' +
            wrapper.current.clientHeight
        )
      }
    } else {
      changeHeight(wrapper)
    }
  }

  // handler for mouseevents in locator-mode
  const handleMouseOut = () => {
    setLocatorPos([2000, 2000])
  }
  const handleMouseover = (e: MouseEvent) => {
    if (e) {
      if (e.buttons === 0) {
        setLocatorPos([e.offsetX, e.offsetY])
        setLocatorValue(
          ((e.offsetX * 100) / svgSize[0]).toFixed(0) +
            ',' +
            ((e.offsetY * 100) / svgSize[1]).toFixed(0)
        )
      }
    }
  }

  // if content-element ist loaded and sized adjust the size of the ovberlay
  useEffect(() => {
    if (wrapper && wrapper.current) {
      if (wrapper.current.clientHeight > 0) {
        changeHeight(wrapper)
      } else {
        changeHeight(wrapper)
      }
    }
  }, [loaded])

  // Add and remove eventlistener for locator mode
  useEffect(() => {
    if (svg && svg.current) {
      if (locator) {
        svg.current.addEventListener('mousemove', handleMouseover)
        svg.current.addEventListener('mouseleave', handleMouseOut)
      }
    }
    return () => {
      if (svg && svg.current) {
        svg.current.removeEventListener('mousemove', handleMouseover)
        svg.current.addEventListener('mouseleave', handleMouseOut)
      }
    }
  }, [svgSize])

  return (
    <div className='cbAnnotationLayer' id={id && id}>
      <figure
        className='wrapper'
        ref={wrapper}
        onLoad={() => {
          setLoaded(true)
        }}
      ><>
      
        {children}
        <div className='overlayContainer'>
          <svg
            ref={svg}
            className={locator ? 'overlay locator' : 'overlay'}
            version='1.1'
            xmlns='http://www.w3.org/2000/svg'
            xmlnsXlink='http://www.w3.org/1999/xlink'
            x='0px'
            y='0px'
            viewBox={viewBox}
            xmlSpace='preserve'
            preserveAspectRatio='xMidYMid meet'
          >
            <defs>
              <marker
                id='arrow'
                viewBox='0 0 10 10'
                refX='5'
                refY='5'
                markerWidth='6'
                markerHeight='6'
                orient='auto-start-reverse'
              >
                <path d='M 0 0 L 10 5 L 0 10 z' />
              </marker>
              <marker
                id='dot'
                viewBox='0 0 10 10'
                refX='5'
                refY='5'
                markerWidth='6'
                markerHeight='6'
                orient='auto-start-reverse'
              >
                <circle cx='5' cy='5' r='4' fill='black' />
              </marker>
            </defs>

            {svgSize[1] !== 0 &&
              annotations &&
              annotations.map((anno, i) => {
                return (
                  <OffsetAnnotation
                    key={i}
                    content={anno.content}
                    position={[anno.x, anno.y]}
                    offset={[anno.offsetX || 0, anno.offsetY || 0]}
                    svgSize={svgSize}
                    alignOverwrite={anno.align}
                    Comp={AnnotationComponent}
                    lineHeight={lineHeight}
                    linePadding={linePadding}
                    hideMarker={hideMarker}
                    lineFlow={lineFlow}
                    marker={marker}
                  />
                )
              })}
            {locator && (
              <>
                <g>
                  {gridValues.map((g, i) => {
                    return (
                      <React.Fragment key={i}>
                        <line
                          x1={0}
                          x2={svgSize[0]}
                          y1={(svgSize[1] * g) / 100}
                          y2={(svgSize[1] * g) / 100}
                          className='locatorLine'
                        />
                        <text
                          x='5'
                          y={(svgSize[1] * g) / 100 - 5}
                          className='locatorLineText'
                        >
                          {g}
                        </text>
                        <line
                          y1={0}
                          y2={svgSize[1]}
                          x1={(svgSize[0] * g) / 100}
                          x2={(svgSize[0] * g) / 100}
                          className='locatorLine'
                        />
                        <text
                          y='15'
                          x={(svgSize[0] * g) / 100 + 5}
                          className='locatorLineText'
                        >
                          {g}
                        </text>
                      </React.Fragment>
                    )
                  })}
                </g>
                {locatorValue && (
                  <g
                    transform={
                      'translate(' +
                      locatorPos[0] +
                      ',' +
                      (locatorPos[1] + 30) +
                      ')'
                    }
                  >
                    <rect x='0' y='-20' width='50' height='30' fill='#fff' />
                    <text x='5'>{locatorValue}</text>
                  </g>
                )}
              </>
            )}
          </svg>
        </div>
        </>
      </figure>
    </div>
  )
}
