text: import RBush from 'rbush';
  import { SVG_NAMESPACE } from '@recogito/annotorious/src/util/SVG';
  import { drawShape, shapeArea, svgFragmentToShape } from '@recogito/annotorious/src/selectors';
  import { pointInsidePoygon, isHole} from '@recogito/annotorious/src/selectors/EmbeddedSVG';
  /** 
   * Computes the bounding box of an annotation. WARNING:
   * this is an expensive operation which parses the annotation,
   * creates a temporary SVG element and attaches it to the DOM,
   * uses .getBBox() and then removes the temporary SVG element.  
   */
   export const getBounds = annotation => {
    const shape = drawShape(annotation);
    
    // A temporary SVG buffer, so we can use .getBBox()
    const svg = document.createElementNS(SVG_NAMESPACE, 'svg');
    svg.style.position = 'absolute';
    svg.style.opacity = 0;
    svg.style.top = 0;
    svg.style.left = 0;
  
    svg.appendChild(shape);
    document.body.appendChild(svg);
    
    const { x, y, width, height } = shape.getBBox();  
  
    document.body.removeChild(svg);
  
    return {
      minX: x, 
      minY: y,
      maxX: x + width,
      maxY: y + height
    };
  }
  
  export default class AnnotationStore {
  
    constructor(env) {
      this.env = env;
      
      this.spatial_index = new RBush();
    }
  
    getAnnotationAt = (x, y) => {
      const hits = this.spatial_index.search({
        minX: x,
        minY: y,
        maxX: x,
        maxY: y
      }).map(item => item.annotation);
      if (hits.length > 0) {
        let invalidHitsIndex = []
        //Search for annotations, which bbox is at pointer, yet not annotation is not.
        for (let i=0; i < hits.length; i++) {
          const selector = hits[i].selector('SvgSelector');
          if (selector){
            if ((selector.value?.match(/^<svg.*<path d=/g))){
              let polygon = []
              let multiPolygon = []
              for (var points of svgFragmentToShape(hits[i]).animatedPathSegList){
                if(points.x){
                  if (points.pathSegType === 2){
                    if (polygon.length>0){
                      multiPolygon.push(polygon)
                    }
                    polygon = [[points.x,points.y]]
                  } else {
                    polygon.push([points.x,points.y])
                  }
                } else {
                  multiPolygon.push(polygon)
                }
              }
              console.log(multiPolygon);
              let isAt = false
              let holes = []
              for (const poly of multiPolygon){
                let isAHole = false
                for (const poly2 of multiPolygon){
                  if (isHole(poly,poly2)){
                    holes.push(poly)
                    isAHole = true
                    break
                  }
                }
                if (!isAHole){
                  if (pointInsidePoygon([x,y], poly)){
                    isAt = true
                  }
                }
              }
              if (isAt){
                for (const hole of holes){
                  if (pointInsidePoygon([x,y], hole)){
                    isAt = false
                    break
                  }
                }
              }
              if (!isAt){
                invalidHitsIndex.push(i)
              }
            } else if ((selector.value?.match(/^<svg.*<polygon/g))){
              const points = svgFragmentToShape(hits[i]).getAttribute('points')
              .split(' ') // Split x/y tuples
              .map(xy => xy.split(',').map(str => parseFloat(str.trim())));
              if (!pointInsidePoygon([x,y], points)){
                invalidHitsIndex.push(i)
              }
            }
            for (const invalidHit of invalidHitsIndex){
              hits.splice(invalidHit, 1);
            }
          }
        }
        // Get smallest annotation
        hits.sort((a, b) => shapeArea(a, this.env.image) - shapeArea(b, this.env.image));
        return hits[0];
      }
    }
  
    getAnnotationsIntersecting = bounds =>
      this.spatial_index.search(bounds).map(item => item.annotation);
  
    insert = arg => {
      const annotations = Array.isArray(arg) ? arg : [ arg ];
      annotations.forEach(annotation => {
        this.spatial_index.insert({
          ...getBounds(annotation), annotation
        })
      });
    }
  
    remove = annotation => {
      // Unfortunately, .remove currently requires bounds,
      // therefore we need to re-compute. See:
      // https://github.com/mourner/rbush/issues/95
      const item = {
        ...getBounds(annotation),
        annotation
      };
  
      this.spatial_index.remove(item, (a, b) =>
        a.annotation.id === b.annotation.id);
    }
  
  }