import java.awt.{BorderLayout, Color, Dimension, Font, Graphics, Graphics2D, Rectangle, RenderingHints}
import java.awt.event.{MouseAdapter, MouseEvent}

import javax.swing.{JFrame, JPanel}

object FlippingBitsGame extends App {

  class FlippingBitsGame extends JPanel {
    private val maxLevel: Int = 7
    private val box: Rectangle = new Rectangle(120, 90, 400, 400)

    private var n: Int = maxLevel

    private var grid: Array[Array[Boolean]] = _
    private var target: Array[Array[Boolean]] = _

    private var solved: Boolean = true

    override def paintComponent(gg: Graphics): Unit = {
      def drawGrid(g: Graphics2D): Unit = {
        if (solved) g.drawString("Solved! Click here to play again.", 180, 600)
        else g.drawString("Click next to a row or a column to flip.", 170, 600)
        val size: Int = box.width / n
        for {r <- 0 until n
             c <- 0 until n} {
          g.setColor(if (grid(r)(c)) Color.blue else Color.orange)
          g.fillRect(box.x + c * size, box.y + r * size, size, size)
          g.setColor(getBackground)
          g.drawRect(box.x + c * size, box.y + r * size, size, size)
          g.setColor(if (target(r)(c)) Color.blue else Color.orange)
          g.fillRect(7 + box.x + c * size, 7 + box.y + r * size, 10, 10)
        }
      }

      super.paintComponent(gg)
      val g: Graphics2D = gg.asInstanceOf[Graphics2D]
      g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
      drawGrid(g)
    }

    private def printGrid(msg: String, g: Array[Array[Boolean]]): Unit = {
      println(msg)
      for (row <- g) println(row.mkString(", "))
      println()
    }

    private def startNewGame(): Unit = {
      val rand = scala.util.Random

      if (solved) {
        val minLevel: Int = 3
        n = if (n == maxLevel) minLevel else n + 1
        grid = Array.ofDim[Boolean](n, n)
        target = Array.ofDim[Boolean](n, n)

        do {
          def shuffle(): Unit = for (i <- 0 until n * n)
            if (rand.nextBoolean()) flipRow(rand.nextInt(n)) else flipCol(rand.nextInt(n))

          shuffle()
          for (i <- grid.indices) grid(i).copyToArray(target(i))