package controllers

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

object NotifyController extends Controller{
  val inject = Guice.createInjector(new ServiceModules)
  val sendMail = inject.getInstance(classOf[SendMail])

  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) = 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.createNotifyForm(notifyRegistForm.fill(NotifyForm("", logInUser, "", null)) , 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 = UserManager().getByName(notify.users.name)
            val paramState = Integer.decode(notify.state)
            val newNotify = NotifyManager().insert(notify, notifyType, partId, designChangeId, paramState)
            request.body.file("atach").map { atach =>
            	AtachManager().uploadAtach(atach, notify.atach.grpName, 0, newNotify.id, 0)
              }
            var usersBuffer = Seq[User]()
              // 部品通知の場合
            if(partId != 0) {
              val targetPart = newNotify.part.head
            	val users = targetPart.project.head.users
            	for(user <- users) {
            		sendMail.sendMail(notifyType, announceUser.email, targetPart.id, 0, notifyType, paramState.longValue(), user.email)
            	}
              // 設計変更通知の場合
            } else {
            	 //設計変更対象リレーションの抽出
               val targetRelations = DesignChangeManager().getTargetRelationByDesignChangeId(designChangeId)
                 //各リレーションの上位品番と子品番のプロジェクトメンバー抽出
               for(targetRelation <- targetRelations) {
                 var users = targetRelation.parent.head.project.head.users
                 for(user <- users) {
                   usersBuffer = usersBuffer.:+(user)
                    }
                 users = targetRelation.child.head.project.head.users
                 for(user <- users) {
                   usersBuffer = usersBuffer.:+(user)
                   }
                 }
                //前述処理で抽出した全メンバーにメイル送信
              for(user <- usersBuffer.distinct) {
                sendMail.sendMail(notifyType, announceUser.email, 0, designChangeId, notifyType, paramState.longValue(), user.email)
                }
            }
          Ok(views.html.issueresult(notifyType, notifyType))
          }
        }
    )
  }

  def showNotify(id: Long, partId: Long, designChangeId: Long, notifyType: Long, state: Long) = AuthAction {
    Action { implicit request =>
      if(request == null) {
        Ok(views.html.errors.errorNotAuthentication())        
      } else {
        inTransaction {
          val notify = NotifyManager().getById(id)
          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, designChangeId, notifyType, state, notify))
          }
      }
    }
  }

  def updateState(id: Long, partId: Long, designChangeId: Long, notifyType: Long, state: Long) = Action { implicit request =>
    inTransaction {
      val notify = NotifyManager().getById(id)
      notify.state = 1
      NotifyManager().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, designChangeId: Long, notifyType, state, notify))
    }
  }
  
  def appendAtach(id: Long, partId: Long, designChangeId: Long, notifyType: Long, state: Long) = Action(parse.multipartFormData) { implicit request =>
    notifyRegistForm.bindFromRequest.fold(
        formWithErrors => BadRequest(views.html.showNotifyForm(formWithErrors, id, partId, designChangeId, 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, designChangeId, notifyType, state))
          }
        }
    )
  }
  
  def listRecursion(page: Int, partId: Long, notifyType: Long, state: Long) = AuthAction {
    Action { implicit request =>
      if(request == null) {
        Ok(views.html.errors.errorNotAuthentication())
      } else {
        var notifyBuffer = Seq[NotifyBean]()
        inTransaction {
          val row = Integer.decode(Messages("list.row"))
          val notifyPart = PartManager().getById(partId)
          if(state==9) {
            notifies = notifyPart.notifies.where(n => n.notifyType === notifyType)
          } else {
            notifies = notifyPart.notifies.where(n => n.notifyType === notifyType and n.state === state)
            }
          for(notify <- notifies) {
            var i:Int =0
            notifyBuffer = notifyBuffer.:+(NotifyBean(i, notify.message, notify.user.head.name, notify.id, Messages("notify.state" + notify.state), notify.atachs))
            for(reply <- notify.replies) {
              //    	    ReplyRecursion().down(reply, notifyBuffer, i)
              for(returnNotifyBuffer <- ReplyRecursion().down(reply, i)) {
                notifyBuffer = notifyBuffer.:+(returnNotifyBuffer)
                }
              }
            }
          Ok(views.html.notifylist(notifyBuffer.drop(page*row).take(row), notifyBuffer.size, partId, 0, notifyPart.name, page, notifyType, state))
          }
        }
      }
    }
  
  
  def designChangeListRecursion(page: Int, designChangeId: Long, notifyType: Long, state: Long) = AuthAction {
    Action { implicit request =>
      if(request == null) {
        Ok(views.html.errors.errorNotAuthentication())        
      } else {
        var notifyBuffer = Seq[NotifyBean]()
        inTransaction {
          val row = Integer.decode(Messages("list.row"))
          val designChange = DesignChangeManager().getById(designChangeId)
          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 = 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) {
              for(returnNotifyBuffer <- ReplyRecursion().down(reply, i)) {
                notifyBuffer = notifyBuffer.:+(returnNotifyBuffer)
                }
              }
            }
          Ok(views.html.notifylist(notifyBuffer.drop(page*row).take(row), notifyBuffer.size, 0, designChange.id, designChange.dcNo, page, notifyType, state))
          }
        }
      }
  }
  
}