package controllers

import play.api._
import play.api.i18n._
import play.api.mvc._
import play.api.data._
import play.api.data.Forms._
import play.api.data.validation.Constraints._
import forms._
import models._
import models.services._
import infra.services._
import beans._
import org.squeryl._
import org.squeryl.PrimitiveTypeMode._
import scala.collection.mutable.ArrayBuffer

object NotifyController extends Controller{

  var notifies :org.squeryl.Query[Notify] = null

  val notifyRegistForm = Form(
      mapping(
          "message" -> nonEmptyText,
          "users" -> mapping(
        		  "name" -> nonEmptyText
          )(UserForm.apply)(UserForm.unapply),
          "state" -> text,
          "atach" -> mapping(
              "grpName" -> text
           )(AtachForm.apply)(AtachForm.unapply)
      )(NotifyForm.apply)(NotifyForm.unapply)
  )
  
  def createNotify(partId: Long, designChangeId: Long, notifyType: Long) = Action{ implicit request =>
    	Ok(views.html.createNotifyForm(notifyRegistForm, partId, designChangeId, notifyType))
  }
  
  def notifyRegistration(partId: Long, designChangeId: Long, notifyType: Long) = Action(parse.multipartFormData) { implicit request =>
    notifyRegistForm.bindFromRequest.fold(
        formWithErrors => BadRequest(views.html.createNotifyForm(formWithErrors, partId, designChangeId, notifyType)),
//        formWithErrors => BadRequest(views.html.error(formWithErrors)),
        notify => {
          inTransaction {
            val announceUser = PartsListDb.users.where(u => u.name === notify.users.name).head
            val paramState = Integer.decode(notify.state)
            val newNotify = PartsListDb.notifies.insert(Notify(notify.message, notify.atach, announceUser.id, notifyType, partId, designChangeId, paramState))
            var usersBuffer = ArrayBuffer[User]()
            request.body.file("atach").map { atach =>
            	AtachManager().uploadAtach(atach, newNotify.atach.grpName, 0, newNotify.id, 0)
              }
              // 部品通知の場合
            if(partId != 0) {
            	val targetPart = PartsListDb.parts.where(p => p.id === partId).head
            	val users = targetPart.project.assign(targetPart.project.head).users
            	val sendMail = SendMail(notifyType, announceUser.email, targetPart.id, 0, notifyType, paramState.longValue())
            	for(user <- users) {
            		sendMail.sendMail(user.email)
            	}
              // 設計変更通知の場合
            } else {
            	 //設計変更対象リレーションの抽出
               val targetRelations = PartsListDb.designChanges.where(dc => dc.id === designChangeId ).head.delPartRelation.++:(PartsListDb.designChanges.where(dc2 => dc2.id === designChangeId).head.addPartRelation)
                 //各リレーションの上位品番と子品番のプロジェクトメンバー抽出
               for(targetRelation <- targetRelations) {
                 var users = targetRelation.parent.head.project.assign(targetRelation.parent.head.project.head).users
                 users.copyToBuffer(usersBuffer)
                 users = targetRelation.child.head.project.assign(targetRelation.child.head.project.head).users
                 users.copyToBuffer(usersBuffer)
                 }
                //前述処理で抽出した全メンバーにメイル送信
              val sendMail = SendMail(notifyType, announceUser.email, 0, designChangeId, notifyType, paramState.longValue())
              for(user <- usersBuffer.distinct) {
                sendMail.sendMail(user.email)
                }
            }
          Ok(views.html.issueresult(notifyType, notifyType))
          }
        }
    )
  }

  def showNotify(id: Long, partId: Long, notifyType: Long, state: Long) = Action { implicit request =>
    inTransaction {
      val notify = PartsListDb.notifies.where(n => n.id === id).head
      val notifyForm = NotifyForm(notify.message, UserForm(notify.user.assign(notify.user.head).name), Messages("notify.state" + notify.state), null)
      Ok(views.html.showNotifyForm(notifyRegistForm.fill(notifyForm), id, partId, notifyType, state, notify))
    }
  }

  def updateState(id: Long, partId: Long, notifyType: Long, state: Long) = Action {
    inTransaction {
      val notify = PartsListDb.notifies.where(n => n.id === id).head
      notify.state = 1
      PartsListDb.notifies.update(notify)
      val notifyForm = NotifyForm(notify.message, UserForm(notify.user.assign(notify.user.head).name), Messages("notify.state" + notify.state), null)
      Ok(views.html.showNotifyForm(notifyRegistForm.fill(notifyForm),id, partId, notifyType, state, notify))
    }
  }
  
  def appendAtach(id: Long, partId: Long, notifyType: Long, state: Long) = Action(parse.multipartFormData) { implicit request =>
    notifyRegistForm.bindFromRequest.fold(
        formWithErrors => BadRequest(views.html.showNotifyForm(formWithErrors, id, partId, notifyType, state, null)), 
        notify => {
          inTransaction {
            request.body.file("atach").map{ atach =>
                AtachManager().uploadAtach(atach, notify.atach.grpName, 0, id, 0)
              }
            Redirect(routes.NotifyController.showNotify(id, partId, notifyType, state))
          }
        }
    )
  }
  
  def listRecursion(page: Int, partId: Long, notifyType: Long, state: Long) = Action { implicit request =>
    val notifyBuffer = ArrayBuffer[NotifyBean]()
    inTransaction {
      val row = Integer.decode(Messages("list.row"))
      val notifyPart = PartsListDb.parts.where(p => p.id === partId).head
      if(state==9) {
    	  notifies = notifyPart.notifies.where(n => n.partId === partId and n.notifyType === notifyType)
       } else {
         notifies = notifyPart.notifies.where(n => n.partId === partId and n.notifyType === notifyType and n.state === state)
       }
      for(notify <- notifies) {
    	  var i:Int =0
    	  notifyBuffer += NotifyBean(i, notify.message, notify.user.assign(notify.user.head).name, notify.id, Messages("notify.state" + notify.state), notify.atachs)
    	  for(reply <- notify.replies) {
    	    Recursion(reply, notifyBuffer, i)
    	  }
       }
      Ok(views.html.notifylist(notifyBuffer.drop(page*row).take(row), notifyBuffer.size, notifyPart.id, notifyPart.name, page, notifyType, state))
    }
  }
  
  def Recursion(reply: Reply, notifyBuffer: ArrayBuffer[NotifyBean], i: Int):Unit = {
    var level = i+1
    notifyBuffer += NotifyBean(level, reply.message, reply.user.assign(reply.user.head).name, reply.id, Messages("notify.state9"), reply.atachs)
    for( childReply <- reply.childReplies) {
      Recursion(childReply, notifyBuffer, level)
    }
  }
  
  def designChangeListRecursion(page: Int, designChangeId: Long, notifyType: Long, state: Long) = Action { implicit request =>
    val notifyBuffer = ArrayBuffer[NotifyBean]()
    inTransaction {
      val row = Integer.decode(Messages("list.row"))
      val designChange = PartsListDb.designChanges.where(dc => dc.id === designChangeId).head
      if(state==9) {
    	  notifies = designChange.notifies.where(n => n.notifyType === notifyType)
      } else {
         notifies = designChange.notifies.where(n => n.notifyType === notifyType and n.state === state)
       }
      for(notify <- notifies) {
        var i:Int =0
        notifyBuffer += NotifyBean(i, notify.message, notify.user.assign(notify.user.head).name, notify.id, Messages("notify.state" + notify.state), notify.atachs)
        for(reply <- notify.replies) {
          Recursion(reply, notifyBuffer, i)
        }
      }
      Ok(views.html.notifylist(notifyBuffer.drop(page*row).take(row), notifyBuffer.size, designChange.id, designChange.dcNo, page, notifyType, state))
    }
  }
}