package pl.edu.pw.mini.sg.movingtargets.coverage

import argonaut.Json
import canes.game.{AllUnitsPositions, PureDefenderStrategy}
import pl.edu.pw.mini.jk.sg.game.NormalizableFactory
import pl.edu.pw.mini.jk.sg.game.immutable.mutable.MutableWrapper
import pl.edu.pw.mini.sg.movingtargets.DefenderPosition
import pl.edu.pw.mini.sg.movingtargets.helpers.FactoryWithJsonOutput
import pl.edu.pw.mini.sg.movingtargets.{AttackerDecision, MovingTargetsAttackerState, MovingTargetsGameConfig}

import scala.collection.JavaConverters._

final case class CoverageNormalizableFactory(game: MovingTargetsGameConfig) extends NormalizableFactory[AttackerDecision, CoverageDefenderMove, MutableWrapper[AttackerDecision, CoverageDefenderMove, MovingTargetsAttackerState, CoverageDefenderStateCached, CoverageImmutableGame]] with FactoryWithJsonOutput[CoverageDefenderMove] {

  override def gameConfig: pl.edu.pw.mini.sg.movingtargets.MovingTargetsGameConfig = game

  val initialState = CoverageImmutableGame.initialState(game)
  private val positionHelper: CoveragePositionsHelper = initialState.positionHelper

  override def convertPureStrategy(seq: java.util.List[CoverageDefenderMove]): PureDefenderStrategy =
    PureDefenderStrategy(seq.asScala.zipWithIndex.foldLeft(List(Vector(game.defenderStartingPositions))) {
      case (possiblePlays, (coverage, idx)) => {
        val possibleNext: Vector[List[DefenderPosition]] = positionHelper.coveragePositions(idx + 1)(coverage.coveredTargetIds)
        possibleNext
          .map(pn => possiblePlays.find(x => x.last.zip(pn).forall((gameConfig.isProperMove _).tupled)).map(x => x :+ pn.toVector))
          .collect { case Some(x) => x }.toList
      }
    }.head.map(v =>
      AllUnitsPositions(v.map(gameConfig.toDoublePositions(_)).toList)).tail)

  override def create() = new MutableWrapper(initialState)

  override def denormalize = this
  override def normalize = this
}
