/**
 * GridGeometry: manage and convert grid coordinates
 */
import memoize from 'memoizee'
import {settings, tileEdgeRange, canvasDimensions} from '../constants'
import PointyTopHexagonShape from './shapes/PointyTopHexagonShape'

const TILE_OFFSET = 1

// tile margins must be even to not break Importer._getTilePosition()
export const IMPORT_TILE_MARGINS = 6

const shape = new PointyTopHexagonShape()

class GridGeometry {
  constructor() {
    this.tileCenterPoint = memoize(this._tileCenterPoint, {
      normalizer: (args) => {
        return `x${args[0].x}y${args[0].y}`
      },
    })
    this.getPointsAround = memoize(this._getPointsAround, {
      normalizer: (args) => {
        return `x${args[0].x}y${args[0].y}`
      },
    })

    this.setTileEdge(tileEdgeRange.default)
  }

  setTileEdge(tileEdge) {
    if (isNaN(tileEdge)) {
      console.warn('setting NaN tile edge, something probably went wrong')
    }
    this._tileEdge = tileEdge
    this.resize()
  }

  setTileEdgeFromMax(maxX, maxY) {
    const tileEdge = shape.getTileEdgeFromGridUnit({
      width: canvasDimensions.width / (maxX + IMPORT_TILE_MARGINS),
      height: canvasDimensions.height / (maxY + IMPORT_TILE_MARGINS),
    })
    this.setTileEdge(tileEdge)
  }

  setTileEdgeFromArea(area) {
    const tileEdge = shape.getTileEdgeFromArea(area)
    this.setTileEdge(tileEdge)
  }

  getTileEdge() {
    return this._tileEdge
  }

  getTileDimensions() {
    return this._tileSize
  }

  getUnitOffsetX(y) {
    return shape.getUnitOffsetX(y)
  }

  getUnitOffsetY(x) {
    return shape.getUnitOffsetY(x)
  }

  getDrawOffsetX(y) {
    return shape.getDrawOffsetX(y)
  }

  getDrawOffsetY(x) {
    return shape.getDrawOffsetY(x)
  }

  getTileCounts() {
    return this._tileCounts
  }

  resize() {
    this._tileSize = shape.getTileSize(this._tileEdge)
    const gridUnit = shape.getGridUnit()
    this._tileCounts = {
      width: Math.floor(
        (canvasDimensions.width / (this._tileSize.width * gridUnit.width)) -
        (TILE_OFFSET * 2)
      ),
      height: Math.floor(
        (canvasDimensions.height / (this._tileSize.height * gridUnit.height)) -
        (TILE_OFFSET * 2)
      ),
    }
    this.tileCenterPoint.clear()
    this.getPointsAround.clear()
  }

  forEachTilePosition(iterator) {
    for (let x = TILE_OFFSET - 2; x < this._tileCounts.width + 3; x++) {
      for (let y = TILE_OFFSET - 2; y < this._tileCounts.height + 3; y++) {
        iterator(x, y)
      }
    }
  }

  /** Return X/Y center point of tile at given position */
  _tileCenterPoint(position) {
    const gridUnit = shape.getGridUnit()
    return {
      x: this._tileSize.width * (
        ((position.x + TILE_OFFSET) * gridUnit.width) +
        this.getDrawOffsetX(position.y)
      ),
      y: this._tileSize.height * (
        ((position.y + TILE_OFFSET) * gridUnit.height) +
        this.getDrawOffsetY(position.x)
      ),
    }
  }

  _getPointsAround(center, contiguous) {
    const tileScale = contiguous ? 1.0 : settings.tileScale
    const scaledSize = {
      width: this._tileSize.width * tileScale,
      height: this._tileSize.height * tileScale,
    }
    return shape.getPointsAround(center, scaledSize)
  }

  /**
   * Return grid position, given screen coordinates.
   * NOTE: The order that X and Y can be calculated depends on the shape
   * because of grid offsets.
   */
  getPositionFromScreen(screenX, screenY) {
    const gridUnit = shape.getGridUnit()
    const y =
      Math.round(
        (
          screenY /
          ((this._tileSize.height * gridUnit.height) / devicePixelRatio)
        ) - this.getDrawOffsetY()
      ) - TILE_OFFSET
    const x =
      Math.round(
        (
          screenX /
          ((this._tileSize.width * gridUnit.width) / devicePixelRatio)
        ) - this.getDrawOffsetX(y)
      ) - TILE_OFFSET
    return {x, y}
  }
}

export default new GridGeometry()

@@ -436,24 +436,27 @@
 ctor() %7B%0A   
+ //
  this.tileCe
@@ -499,24 +499,27 @@
 Point, %7B%0A   
+ //
    normalize
@@ -529,36 +529,39 @@
 (args) =%3E %7B%0A    
+//
     
+ 
 return %60x$%7Bargs%5B
@@ -575,32 +575,35 @@
 %7Bargs%5B0%5D.y%7D%60%0A   
+ //
    %7D,%0A    %7D)%0A   
@@ -591,31 +591,37 @@
  //   %7D,%0A   
+ //
  %7D)%0A   
+ //
  this.getPoi
@@ -668,16 +668,19 @@
 d, %7B%0A   
+ //
    norma
@@ -697,24 +697,27 @@
 gs) =%3E %7B%0A   
+ //
      return 
@@ -744,24 +744,27 @@
 s%5B0%5D.y%7D%60%0A   
+ //
    %7D,%0A    %7D)
@@ -761,18 +761,119 @@
  %7D,%0A    
-%7D)
+// %7D)%0A    this.tileCenterPoint = this._tileCenterPoint%0A    this.getPointsAround = this._getPointsAround
 %0A%0A    th
@@ -2312,24 +2312,27 @@
 ),%0A    %7D%0A   
+ //
  this.tileCe
@@ -2348,24 +2348,27 @@
 .clear()%0A   
+ //
  this.getPoi

undo memoization