
import * as cornerstoneTools from 'cornerstone-tools'
const external = cornerstoneTools.external
// Drawing
const getNewContext = cornerstoneTools.import('drawing/getNewContext')
const draw = cornerstoneTools.import('drawing/draw')
const setShadow = cornerstoneTools.import('drawing/setShadow')
const drawLine = cornerstoneTools.import('drawing/drawLine')

const toolStyle = cornerstoneTools.toolStyle
// const toolColors = cornerstoneTools.toolColors
const color = '#fff'

/**
 * @public
 * @class ScaleOverlayTool
 * @memberof Tools
 *
 * @classdesc Tool for displaying a scale overlay on the image.
 * @extends Tools.Base.BaseTool
 */
export default class ScaleOverlayTool extends cornerstoneTools.ScaleOverlayTool {
  constructor(props = {}) {
    const defaultProps = {
      name: 'ScaleOverlay',
      configuration: {
        minorTickLength: 5,
        majorTickLength: 10
      },
      mixins: ['enabledOrDisabledBinaryTool']
    }

    super(props, defaultProps)
  }

  enabledCallback(element) {
    this.forceImageUpdate(element)
  }

  disabledCallback(element) {
    this.forceImageUpdate(element)
  }

  forceImageUpdate(element) {
    const enabledElement = external.cornerstone.getEnabledElement(element)

    if (enabledElement.image) {
      external.cornerstone.updateImage(element)
    }
  }

  renderToolData(evt) {
    const eventData = evt.detail

    const context = getNewContext(eventData.canvasContext.canvas)
    const { image, viewport, element } = eventData

    let rowPixelSpacing = image.rowPixelSpacing
    let colPixelSpacing = image.columnPixelSpacing
    const imagePlane = external.cornerstone.metaData.get(
      'imagePlaneModule',
      image.imageId
    )

    if (imagePlane) {
      rowPixelSpacing =
        imagePlane.rowPixelSpacing || imagePlane.rowImagePixelSpacing
      colPixelSpacing =
        imagePlane.columnPixelSpacing || imagePlane.colImagePixelSpacing
    }

    // Check whether pixel spacing is defined
    if (!rowPixelSpacing || !colPixelSpacing) {
      // logger.warn(
      //   `unable to define rowPixelSpacing or colPixelSpacing from data on ${this.name}'s renderToolData`
      // )

      return
    }

    const canvasSize = {
      width: context.canvas.width,
      height: context.canvas.height
    }

    // Distance between intervals is 10mm
    const verticalIntervalScale = (10.0 / rowPixelSpacing) * viewport.scale
    const horizontalIntervalScale = (10.0 / colPixelSpacing) * viewport.scale
    // 0.1 and 0.05 gives margin to horizontal and vertical lines
    // const hscaleBounds = computeScaleBounds(canvasSize, 0.25, 0.05)
    // const vscaleBounds = computeScaleBounds(canvasSize, 0.05, 0.15)
    const hscaleBounds = computeScaleBounds(canvasSize, 0.4, 0.04)
    const vscaleBounds = computeScaleBounds(canvasSize, 0.04, 0.4)

    if (
      !canvasSize.width ||
      !canvasSize.height ||
      !hscaleBounds ||
      !vscaleBounds
    ) {
      return
    }

    // const color = toolColors.getToolColor()
    const lineWidth = toolStyle.getToolWidth()

    const imageAttributes = Object.assign(
      {},
      {
        hscaleBounds,
        vscaleBounds,
        verticalMinorTick: verticalIntervalScale,
        horizontalMinorTick: horizontalIntervalScale,
        verticalLine: {
          start: {
            x: vscaleBounds.bottomRight.x,
            y: vscaleBounds.topLeft.y
          },
          end: {
            x: vscaleBounds.bottomRight.x,
            y: vscaleBounds.bottomRight.y
          }
        },
        horizontalLine: {
          start: {
            x: hscaleBounds.topLeft.x,
            y: hscaleBounds.bottomRight.y
          },
          end: {
            x: hscaleBounds.bottomRight.x,
            y: hscaleBounds.bottomRight.y
          }
        },
        color,
        lineWidth
      },
      this.configuration
    )

    draw(context, context => {
      setShadow(context, imageAttributes)

      // Draw vertical line
      drawLine(
        context,
        element,
        imageAttributes.verticalLine.start,
        imageAttributes.verticalLine.end,
        {
          color: imageAttributes.color,
          lineWidth: imageAttributes.lineWidth
        },
        'canvas'
      )
      drawVerticalScalebarIntervals(context, element, imageAttributes)

      // Draw horizontal line
      drawLine(
        context,
        element,
        imageAttributes.horizontalLine.start,
        imageAttributes.horizontalLine.end,
        {
          color: imageAttributes.color,
          lineWidth: imageAttributes.lineWidth
        },
        'canvas'
      )
      drawHorizontalScalebarIntervals(context, element, imageAttributes)
    })
  }
}

/**
 * Computes the max bound for scales on the image
 * @param  {{width: number, height: number}} canvasSize
 * @param  {number} horizontalReduction
 * @param  {number} verticalReduction
 * @returns {Object.<string, { x:number, y:number }>}
 */
const computeScaleBounds = (
  canvasSize,
  horizontalReduction,
  verticalReduction
) => {
  const hReduction = horizontalReduction * Math.min(1000, canvasSize.width)
  const vReduction = verticalReduction * Math.min(1000, canvasSize.height)
  const canvasBounds = {
    left: hReduction,
    top: vReduction,
    width: canvasSize.width - 2 * hReduction,
    height: canvasSize.height - 2 * vReduction
  }

  return {
    topLeft: {
      x: canvasBounds.left,
      y: canvasBounds.top
    },
    bottomRight: {
      x: canvasBounds.left + canvasBounds.width,
      y: canvasBounds.top + canvasBounds.height
    }
  }
}

/**
 * @param {CanvasRenderingContext2D} context
 * @param {HTMLElement} element
 * @param {Object} imageAttributes
 * @returns {void}
 */
const drawVerticalScalebarIntervals = (context, element, imageAttributes) => {
  let i = 0

  while (
    imageAttributes.verticalLine.start.y +
      i * imageAttributes.verticalMinorTick <=
    imageAttributes.vscaleBounds.bottomRight.y
  ) {
    const { color, lineWidth } = imageAttributes
    const startPoint = {
      x: imageAttributes.verticalLine.start.x,
      y:
        imageAttributes.verticalLine.start.y +
        i * imageAttributes.verticalMinorTick
    }

    const endPoint = {
      x: 0,
      y:
        imageAttributes.verticalLine.start.y +
        i * imageAttributes.verticalMinorTick
    }

    if (i % 5 === 0) {
      endPoint.x =
        imageAttributes.verticalLine.start.x - imageAttributes.majorTickLength
    } else {
      endPoint.x =
        imageAttributes.verticalLine.start.x - imageAttributes.minorTickLength
    }

    drawLine(
      context,
      element,
      startPoint,
      endPoint,
      {
        color,
        lineWidth
      },
      'canvas'
    )

    i++
  }
}

/**
 * @param {CanvasRenderingContext2D} context
 * @param {HTMLElement} element
 * @param {Object} imageAttributes
 * @returns {void}
 */
const drawHorizontalScalebarIntervals = (context, element, imageAttributes) => {
  let i = 0

  while (
    imageAttributes.horizontalLine.start.x +
      i * imageAttributes.horizontalMinorTick <=
    imageAttributes.hscaleBounds.bottomRight.x
  ) {
    const { color, lineWidth } = imageAttributes
    const startPoint = {
      x:
        imageAttributes.horizontalLine.start.x +
        i * imageAttributes.horizontalMinorTick,
      y: imageAttributes.horizontalLine.start.y
    }

    const endPoint = {
      x:
        imageAttributes.horizontalLine.start.x +
        i * imageAttributes.horizontalMinorTick,
      y: 0
    }

    if (i % 5 === 0) {
      endPoint.y =
        imageAttributes.horizontalLine.start.y -
        imageAttributes.majorTickLength
    } else {
      endPoint.y =
        imageAttributes.horizontalLine.start.y -
        imageAttributes.minorTickLength
    }

    drawLine(
      context,
      element,
      startPoint,
      endPoint,
      {
        color,
        lineWidth
      },
      'canvas'
    )

    i++
  }
}
