<commit_before>package sp.runnerService

import akka.actor._

import com.codemettle.reactivemq._
import com.codemettle.reactivemq.ReActiveMQMessages._
import com.codemettle.reactivemq.model._
import org.json4s.JsonAST.JInt
import sp.domain.logic.IDAbleLogic
import scala.concurrent._
import scala.concurrent.ExecutionContext.Implicits.global
import sp.system.messages._
import sp.system._
import sp.domain._
import sp.domain.Logic._
import sp.extensions._
import sp.psl._
import scala.util.Try
import sp.domain.SOP._


object RunnerService extends SPService {
  val specification = SPAttributes(
    "service" -> SPAttributes(
      "group"-> "runner",
      "description" -> "A service to run SOP's in SP"
    ),
    "SOP" -> KeyDefinition("Option[ID]", List(), Some("")
    )
  )

  val transformTuple  = TransformValue("SOP", _.getAs[ID]("SOP"))
  val transformation = transformToList(transformTuple.productIterator.toList)
  //def props(eventHandler: ActorRef) = Props(classOf[RunnerService], eventHandler)
  def props = ServiceLauncher.props(Props(classOf[RunnerService]))
}

class RunnerService extends Actor with ServiceSupport {
  val serviceID = ID.newID

  def receive = {
    case r@Request(service, attr, ids, reqID) => {
      val replyTo = sender()
      implicit val rnr = RequestNReply(r, replyTo)

      val sopID = transform(RunnerService.transformTuple)
      val core = r.attributes.getAs[ServiceHandlerAttributes]("core").get

      //lista av tuplar som vi gör om till map
      val idMap: Map[ID, IDAble] = ids.map(item => item.id -> item).toMap

      //sop:en finns i idMap, fås som IDAble, men vi gör en for comp så den fås som ID
      val sop = for {
        item <- idMap.get(sopID) if item.isInstanceOf[SOP]
      } yield {
        item.asInstanceOf[SOP]
      }

      //lista med id
      val list = sop.map(runASop)

      replyTo ! Response(List(), SPAttributes("result" -> "done"), rnr.req.service, rnr.req.reqID)
      self ! PoisonPill
    }
  }

  def runASop(sop:SOP): Future[String] = {
    sop match {
      case p: Parallel =>
        println(s"Nu är vi i parallel $p")
        val fSeq = p.sop.map(runASop)
        Future.sequence(fSeq).map { list =>
          "done" //kolla sen så att alla verkligen är done!
        }
      case s: Sequence =>
        println(s"Nu är vi i sequence $s")
        if (s.sop.isEmpty) Future("done")
        else {
          val f = runASop(s.sop.head)
          f.flatMap(str => str match {
            case "done" =>
              runASop(Sequence() ++ s.sop.tail)
          })
        }
      case h: Hierarchy =>
        println(s"Nu är vi i hierarki $h")
        val f = test(h.operation)
        f.map(x => x match {
          case "done" => "done" //return true
          case "error" => "nope"
        })
    }
  }

  val sopMap: Map[SOP, List[SOP]] = Map() //parent -> child
  //Tanken är man skapar en map där föräldrar pekar på  sina barn (key -> value)
  //detta kommer sedan användas när man kör en SOP genom att man börjar med en förälder
  //och kollar vilken typ den har (parallell eller sequence), för att veta hur den ska köra
  //sina barn. När ett barn har kört klart kommer den då säga till sin förälder att den är klar
  //och när alla barn till en förälder körts klart går man vidare i kedjan till nästa förälder
  def createASopMap(sop: SOP): Map[SOP, List[SOP]] ={
    val sopSeq = sop.sop
    val nmbrOfChildren = sopSeq.length-1
    if (sop.sop.isEmpty) {
      sopMap
    }else if (nmbrOfChildren == 0) {
      sopMap + (sop -> List())
    } else if (nmbrOfChildren > 0){
      val sopList = List()
      for(child <- sopSeq){
        child -> sopList
        createASopMap(child)
      }
      sopMap + (sop -> sopList)
    } else {
      println("something went wrong")
    }
    sopMap
  }

def test(id: ID) = Future("done")

/*<commit_msg>add comment to help understand<commit_after>package sp.runnerService

import akka.actor._

import com.codemettle.reactivemq._
import com.codemettle.reactivemq.ReActiveMQMessages._
import com.codemettle.reactivemq.model._
import org.json4s.JsonAST.JInt
import sp.domain.logic.IDAbleLogic
import scala.concurrent._
import scala.concurrent.ExecutionContext.Implicits.global
import sp.system.messages._
import sp.system._
import sp.domain._
import sp.domain.Logic._
import sp.extensions._
import sp.psl._
import scala.util.Try
import sp.domain.SOP._


object RunnerService extends SPService {
  val specification = SPAttributes(
    "service" -> SPAttributes(
      "group"-> "runner",
      "description" -> "A service to run SOP's in SP"
    ),
    "SOP" -> KeyDefinition("Option[ID]", List(), Some("")
    )
  )

  val transformTuple  = TransformValue("SOP", _.getAs[ID]("SOP"))
  val transformation = transformToList(transformTuple.productIterator.toList)
  //def props(eventHandler: ActorRef) = Props(classOf[RunnerService], eventHandler)
  def props = ServiceLauncher.props(Props(classOf[RunnerService]))
}

class RunnerService extends Actor with ServiceSupport {
  val serviceID = ID.newID

  def receive = {
    case r@Request(service, attr, ids, reqID) => {
      val replyTo = sender()
      implicit val rnr = RequestNReply(r, replyTo)

      val sopID = transform(RunnerService.transformTuple)
      val core = r.attributes.getAs[ServiceHandlerAttributes]("core").get

      //lista av tuplar som vi gör om till map
      val idMap: Map[ID, IDAble] = ids.map(item => item.id -> item).toMap

      //sop:en finns i idMap, fås som IDAble, men vi gör en for comp så den fås som ID
      val sop = for {
        item <- idMap.get(sopID) if item.isInstanceOf[SOP]
      } yield {
        item.asInstanceOf[SOP]
      }

      //lista med id
      val list = sop.map(runASop)

      replyTo ! Response(List(), SPAttributes("result" -> "done"), rnr.req.service, rnr.req.reqID)
      self ! PoisonPill
    }
  }

  def runASop(sop:SOP): Future[String] = {
    sop match {
      case p: Parallel =>
        println(s"Nu är vi i parallel $p")
        val fSeq = p.sop.map(runASop)
        Future.sequence(fSeq).map { list =>
          "done" //kolla sen så att alla verkligen är done!
        }
      case s: Sequence =>
        println(s"Nu är vi i sequence $s")
        if (s.sop.isEmpty) Future("done")
        else {
          val f = runASop(s.sop.head)
          f.flatMap(str => str match {
            case "done" =>
              runASop(Sequence() ++ s.sop.tail)
          })
        }
      case h: Hierarchy =>
        println(s"Nu är vi i hierarki $h")
        val f = test(h.operation)
        f.map(x => x match {
          case "done" => "done" //return true
          case "error" => "nope"
        })
    }
  }

  val sopMap: Map[SOP, List[SOP]] = Map() //parent -> child
  //Tanken är man skapar en map där föräldrar pekar på  sina barn (key -> value)
  //detta kommer sedan användas när man kör en SOP genom att man börjar med en förälder
  //och kollar vilken typ den har (parallell eller sequence), för att veta hur den ska köra
  //sina barn. När ett barn har kört klart kommer den då säga till sin förälder att den är klar
  //och när alla barn till en förälder körts klart går man vidare i kedjan till nästa förälder
  // TODO: kanske borde använda en treemap? måste nämligen vara noga med att börja med rätt parent
  def createASopMap(sop: SOP): Map[SOP, List[SOP]] ={
    val sopSeq = sop.sop
    val nmbrOfChildren = sopSeq.length-1
    if (sop.sop.isEmpty) {
      sopMap
    }else if (nmbrOfChildren == 0) {
      sopMap + (sop -> List())
    } else if (nmbrOfChildren > 0){
      val sopList = List()
      for(child <- sopSeq){
        child -> sopList
        createASopMap(child)
      }
      sopMap + (sop -> sopList)
    } else {
      println("something went wrong")
    }
    sopMap
  }

def test(id: ID) = Future("done")

/*
{'fraction_non_alphanumeric': 0.11526639344262295, 'fraction_numerical': 0.0010245901639344263, 'mean_word_length': 2.6152777777777776, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7659000', 'n_tokens_mistral': 2664, 'n_tokens_neox': 2610, 'n_words': 754}