package controllers

import mvc.AuthAction
import play.api._
import play.api.mvc._
import play.api.data._
import play.api.data.Forms._
import forms._
import models._
import models.services._
import infra.services._
import controllers.services._
import org.squeryl._
import org.squeryl.PrimitiveTypeMode._
import scala.collection.immutable.Seq
import com.google.inject._
import modules._

object ReplyController extends Controller{
  val inject = Guice.createInjector(new ServiceModules)
  val sendMail = inject.getInstance(classOf[SendMail])
  val replyRegistForm = Form(
      mapping(
          "message" -> nonEmptyText,
          "users" -> mapping (
              "name" -> nonEmptyText
            )(UserForm.apply)(UserForm.unapply),
            "atach" -> mapping {
                "grpName" -> text
              }(AtachForm.apply)(AtachForm.unapply)
        )(ReplyForm.apply)(ReplyForm.unapply)
   )
   
  def createReply(notifyId: Long, replyId: Long, notifyType: Long, replyType: Long, partId: Long, state: Long) = AuthAction {
    Action { implicit request =>
      if(request == null) {
        Ok(views.html.errors.errorNotAuthentication())
      } else {
        var logInUser = UserForm("")
        request.headers.get("remote_user").map { user =>
          logInUser = UserForm(user)
          }
        Ok(views.html.createReplyForm(replyRegistForm.fill(ReplyForm("", logInUser, null)), notifyId, replyId, replyType, partId, notifyType, state))
      }
    }
  }
  
  def replyRegistration(notifyId: Long, replyId: Long, partId: Long, notifyType: Long, state: Long) = Action(parse.multipartFormData) { implicit request =>
    replyRegistForm.bindFromRequest.fold(
        formWithErrors => BadRequest(views.html.createReplyForm(formWithErrors, notifyId, replyId, 0, partId, notifyType, state)),
        reply => {
          inTransaction {
            val replyUser = UserManager().getByName(reply.users.name)
            val newReply = ReplyManager().insert(reply, replyUser, notifyId, replyId)
            var usersBuffer = Seq[User]()
            request.body.file("atach").map { atach =>
              	AtachManager().uploadAtach(atach, newReply.atach.grpName, 0, 0, newReply.id)
              }
            var notify: Notify = null
            if(notifyId!=0) {
            	// 通知直下のreplyの場合、notifyより対象Partを割り出し、プロジェクトユーザー抽出。メイル通知。
            	notify = NotifyManager().getById(notifyId)
            	} else {
              // reply配下のreplyの場合、再帰処理によりnotify抽出後、対象Partを割り出し、プロジェクトユーザー抽出。メイル通知。
              val targetReply = ReplyManager().getById(replyId)
            	val topReply = ReplyRecursion().up(targetReply)
            	notify = NotifyManager().getById(topReply.notifyId)              
              }
              // 部品表通知/依頼の回答であれば、Notifyが紐付くPartのプロジェクトメンバにメイル通知。
            if(notifyType == 0 || notifyType == 1) {
            	val targetPart = notify.part.head
            	val users = targetPart.project.head.users
            	for(user <- users) {
            		sendMail.sendMail(2, replyUser.email, targetPart.id, 0, notifyType, state, user.email)
            	}
              }
              // 設計変更通知/依頼の回答であれば、Notifyが紐付くDesin ChangeのdelRelation、addRelationの全ての上品番、
              // 子品番のプロジェクトメンバにメイル通知。
            if(notifyType == 3 || notifyType == 4) {
                //設計変更対象リレーションの抽出
              val targetRelations = notify.designCgange.head.delPartRelation.++:(notify.designCgange.head.addPartRelation)
                //各リレーションの上位品番と子品番のプロジェクトメンバー抽出
              for(targetRelation <- targetRelations) {
                var users = targetRelation.parent.head.project.head.users
                for(user <- users) {
                  usersBuffer.:+(user)
                  }
                users = targetRelation.child.head.project.head.users
                for(user <- users) {
                  usersBuffer.:+(user)
                  }
                }
              for(user <- usersBuffer.distinct) {
                sendMail.sendMail(2, replyUser.email, 0, notify.designCgange.head.id, notifyType, state, user.email)
              	}
              }
           }
          Ok(views.html.issueresult(2, notifyType))
         }
     )
  }
  
  def showReply(id: Long, partId: Long, designChangeId: Long, notifyType: Long, replyType: Long, state: Long) = AuthAction {
    Action { implicit request =>
      if(request == null) {
        Ok(views.html.errors.errorNotAuthentication())
      } else {
        inTransaction {
          val reply = ReplyManager().getById(id)
          val replyForm = ReplyForm(reply.message, UserForm(reply.user.assign(reply.user.head).name), null)
          Ok(views.html.showReplyForm(replyRegistForm.fill(replyForm), id, partId, designChangeId, notifyType, replyType, state, reply))
          }
        }
      }
  }
  
  def appendAtach(id: Long, partId: Long, designChangeId: Long, notifyType: Long, replyType: Long, state: Long) = Action(parse.multipartFormData) { implicit request =>
    replyRegistForm.bindFromRequest.fold(
        formWithErrors => BadRequest(views.html.showReplyForm(formWithErrors, id, partId, designChangeId, notifyType, replyType, state, null)),
//        formWithErrors => BadRequest(views.html.error(formWithErrors)),
        reply => {
          inTransaction {
            request.body.file("atach").map { atach =>
              	AtachManager().uploadAtach(atach, reply.atach.grpName, 0, 0, id)
              }
            Redirect(routes.ReplyController.showReply(id, partId, designChangeId, notifyType, replyType, state))
            }
          }
     )
  }
}