package pl.edu.pw.mini.sg.mixed.adjuster.momentum

import pl.edu.pw.mini.sg.rng.RandomGenerator
import org.log4s._
import pl.edu.pw.mini.sg.mixed.IterationInfo
import pl.edu.pw.mini.sg.mixed.adjuster.AssesmentBasedAdjuster
import pl.edu.pw.mini.sg.mixed.tree.MixedStrategyNode



final object MomentumDirectionLimitAdjuster extends AssesmentBasedAdjuster {
  private val logger = getLogger

  override type AdjusterState = Momentum
  override val ost = MomentumOptimizerStateType

  override def updateState(
    oldState: AdjusterState,
    assesments: Seq[Double]
  )(implicit
    rng: RandomGenerator
  ): AdjusterState = {
    val ret = if(assesments.view.zipAll(oldState.momentum, 0.0, 0.0).exists { case (a, b) => Math.signum(a) != Math.signum(b) }) {
      oldState.accumulateAssessments(assesments.toVector)
    } else {
      oldState.extend(assesments.length)
    }
    logger.debug(s"Normalized Momentum value: ${ret.momentum.map(_/ret.normalizer)}")
    logger.debug(s"Normalizer: ${ret.normalizer}")

    ret
  }


  override def updateStrategy(
    mixedStrategyNode: MixedStrategyNode[_,_,_],
    adjusterState: AdjusterState,
    assesments: Seq[Double]
  )(implicit
    rng: RandomGenerator,  iterationInfo: IterationInfo
  ) : Boolean = {
    if(adjusterState.normalizer > 0) {
      mixedStrategyNode.updateBy(adjusterState.momentum.map(_/adjusterState.normalizer))
      true
    } else {
      false
    }   
  }
}
