import java.awt.{BasicStroke, BorderLayout, Color, Dimension,
  Font, FontMetrics, Graphics, Graphics2D, Point, Polygon, RenderingHints}
import java.awt.event.{KeyAdapter, KeyEvent, MouseAdapter, MouseEvent}

import javax.swing.{JFrame, JPanel}

import scala.math.{Pi, cos, sin}

object Honeycombs extends App {
  private val (letters, x1, y1, x2, y2, h, w) = ("LRDGITPFBVOKANUYCESM", 150, 100, 225, 143, 87, 150)

  private class HoneycombsPanel() extends JPanel {
    private val comb: IndexedSeq[Hexagon] =
      for {i <- 0 until 20
           (x: Int, y: Int) =
           if (i < 12) (x1 + (i % 3) * w, y1 + (i / 3) * h)
           else (x2 + (i % 2) * w, y2 + ((i - 12) / 2) * h)
           } yield Hexagon(x, y, w / 3, letters(i))

    override def paintComponent(gg: Graphics): Unit = {
      super.paintComponent(gg)
      val g = gg.asInstanceOf[Graphics2D]
      g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
      g.setFont(new Font("SansSerif", Font.BOLD, 30))
      g.setStroke(new BasicStroke(3))
      comb.foreach(_.draw(g))
    }

    case class Hexagon(x: Int, y: Int, halfWidth: Int, letter: Char,
                       var hasBeenSelected: Boolean = false) extends Polygon {
      private val (baseColor, selectedColor) = (Color.yellow, Color.magenta)

      def setSelected(): Unit = hasBeenSelected = true

      def draw(g: Graphics2D): Unit = {
        val fm: FontMetrics = g.getFontMetrics
        val (asc, dec) = (fm.getAscent, fm.getDescent)

        def drawCenteredString(g: Graphics2D, s: String): Unit = {
          val x: Int = bounds.x + (bounds.width - fm.stringWidth(s)) / 2
          val y: Int = bounds.y + (asc + (bounds.height - (asc + dec)) / 2)
          g.drawString(s, x, y)
        }

        g.setColor(if (hasBeenSelected) selectedColor else baseColor)
        g.fillPolygon(this)
        g.setColor(Color.black)
        g.drawPolygon(this)
        g.setColor(if (hasBeenSelected) Color.black else Color.red)
        drawCenteredString(g, letter.toString)
      }

      for (i <- 0 until 6)
        addPoint((x + halfWidth * cos(i * Pi / 3)).toInt, (y + halfWidth * sin(i * Pi / 3)).toInt)

      getBounds
    }

    addKeyListener(new KeyAdapter() {
      override def keyPressed(e: KeyEvent): Unit = {
        val key = e.getKeyChar.toUpper
        comb.find(_.letter == key).foreach(_.setSelected())
        repaint()
      }
    })

    addMouseListener(new MouseAdapter() {
      override def mousePressed(e: MouseEvent): Unit = {
        val mousePos: Point = e.getPoint

        comb.find(h => h.contains(mousePos)).foreach(_.setSelected())
        repaint()
      }
    })

    setBackground(Color.white)
    setPreferredSize(new Dimension(600, 500))
    setFocusable(true)
    requestFocus()
  }

  new JFrame("Honeycombs") {
    add(new HoneycombsPanel(), BorderLayout.CENTER)
    pack()
    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE)
    setLocationRelativeTo(null)
    setResizable(false)
    setVisible(true)
  }

}