package controllers.services
import scala.collection.immutable.Map
import scala.collection.immutable.Seq
import beans._
import models._
import models.services._
import scala.concurrent.Future
import scala.concurrent.ExecutionContext
import scala.concurrent.Await
import scala.concurrent.duration.Duration
import scala.util.Success
import scala.util.Failure
import org.squeryl.PrimitiveTypeMode._

case class PartsList() {
  def getPartsBuffer(opt:Int, page:Int, key:String, relationKey:String):Seq[PartsListShowBean] = {
    import ExecutionContext.Implicits.global
    var partsBuffer = Seq[PartsListShowBean]()
    val targetParts = PartManager().getByName(key)
    if(targetParts.size != 0) {
//      PartRecursion().down(PartManager().getByName(key).head, 1, opt, relationKey).par.map(rpb => partsBuffer = partsBuffer.:+(rpb))
      val futurePartBuffer:Future[Seq[PartsListShowBean]] = Future{
        inTransaction {
      		PartRecursion().down(PartManager().getByName(key).head, 1, opt, relationKey)
        }
      }
//      futurePartBuffer.map(rpbs => rpbs.par.map(rpb => partsBuffer = partsBuffer.:+(rpb)))

/*      futurePartBuffer onComplete {
        case Success(rpbs) => {
          println("************** Check *********************** = " + rpbs.size)
          rpbs.map(
        		rpb => {
        			partsBuffer = partsBuffer.:+(rpb)
        			println(rpb.parent + "/" + rpb.child.name  )
        		  }
        		)
        }
        case Failure(t) => println("エラーが発生しました。" + t.getMessage())
      }*/

/*      futurePartBuffer map {
        rpbs => {
          println("************** Check *********************** = " + rpbs.size)
          rpbs.map(
        		rpb => {
        			partsBuffer = partsBuffer.:+(rpb)
        			println(rpb.parent + "/" + rpb.child.name  )
        		  }
        		)
        }
      }*/

      // 上の２つの処理は共にNonBlockingなので、部品表の展開をまたず、空のpartsBufferを返却し、画面表示（何も表示されない）
      // 対して、以下の処理は明示的なブロッキング待機なので、部品表展開を待って、partsBufferを蓄積し、画面表示（部品表が表示される）
      Await.result(futurePartBuffer, Duration.Inf).map(rpb => {
        println(rpb.parent + "/" + rpb.child.name  )
        partsBuffer = partsBuffer.:+(rpb)
      })
    }
    println("** Check3 **")
    partsBuffer
  }

  def getMatrixPartsList(partsListBeans: Seq[Seq[PartsListShowBean]], allChildren: Seq[Part]): Map[Part, Seq[MultiPartsListBean]] = {
    var matrixPartsListBeans = Map[Part, Seq[MultiPartsListBean]]()
    // 抽出した各モデル毎の部品表配列に対し、部品の有無をチェエク
    partsListBeans.map(plb => {
      var allChildrenList = Seq[MultiPartsListBean]()
      // 全ての部品一覧作成
      allChildren.distinct.sortBy(p => p.name).map(ch => allChildrenList = allChildrenList.:+(MultiPartsListBean(ch, 1)))
      // 比較対象モデルの部品一覧作成
      var targetChildren = Seq[MultiPartsListBean]()
      plb.par.map(tch => targetChildren = targetChildren.:+(MultiPartsListBean(tch.child, 1)))
      // 全ての部品一覧の各部品が、比較対象モデルの部品一覧に存在するかチェック。
      if(plb.size !=0 ) {
        allChildrenList.par.map(comp => {
          if(!targetChildren.contains(comp)) {
            //存在しない場合、表示をOff
            val position:Int = allChildrenList.indexOf(comp)
            allChildrenList(position).showOn = 0
          }
        })
        // 表示制御済みの部品表配列を蓄積
        matrixPartsListBeans = matrixPartsListBeans.+((PartManager().getByName(plb.head.parent).head, allChildrenList))
        // 構成部品なしの場合、全部品を表示Off
      } else {
        allChildrenList.par.map(ac => ac.showOn = 0)
        // 表示制御済みの部品表配列を蓄積
        matrixPartsListBeans =matrixPartsListBeans.+((null, allChildrenList))
      }
    })
    matrixPartsListBeans
  }

}