package controllers

import play.api._
import play.api.data._
import play.api.data.Forms._
import play.api.mvc._
import play.api.i18n._
import org.squeryl._
import org.squeryl.PrimitiveTypeMode._
import views._
import models._
import beans._
import forms._
import scala.collection.mutable.ArrayBuffer

object PartsListController extends Controller{
  
   val Home = Redirect(routes.PartsListController.index(0,0,""))
   val Home2 = Redirect(routes.PartsListController.relationRegistration())
   val relationForm = Form(
       mapping(
           "parent" -> nonEmptyText,
           "child" -> nonEmptyText,
           "quantity" -> longNumber
        )(PartsListBean.apply)(PartsListBean.unapply)
    )
    
    val designChangeRegistForm = Form(
        mapping(
            "partsListBeanBefore" -> mapping(
                "parent" -> nonEmptyText,
                "child" -> text,
                "quantity" -> longNumber
                )(PartsListBean.apply)(PartsListBean.unapply),
              "partsListBeanAfter" -> mapping(
                  "parent" -> nonEmptyText,
                  "child" -> text,
                  "quantity" -> longNumber
                  )(PartsListBean.apply)(PartsListBean.unapply),
            "dcno" -> nonEmptyText
         )(DesignChangeRelationForm.apply)(DesignChangeRelationForm.unapply)
     )
   
	def index(opt:Int, page:Int, key:String) = Action { implicit request =>
		var partBuffer = ArrayBuffer[PartsListBean]()
	    inTransaction {
		  for (parentPart <- PartsListDb.parts.where(p => p.name like key + "%" )) {
			  Recursion(parentPart, partBuffer, opt)
		  }
	    }
	  val row = Integer.decode(Messages("list.row"))
	  Ok(views.html.partslistshow(partBuffer.drop(page*row).take(row), opt, page, partBuffer.size, key))
	}

	def upIndex(opt:Int, page:Int, key:String) = Action {
	  var partBuffer = ArrayBuffer[PartsListBean]()
	  inTransaction {
		  for (childPart <- PartsListDb.parts.where(p => p.name like key +"%")) {
		    UpRecursion(childPart, partBuffer, opt)
		  }
	   }
	   val row = Integer.decode(Messages("list.row"))
	   Ok(views.html.uppartslistshow(partBuffer.drop(page*row).take(row), opt, page, partBuffer.size, key))
	}
	
	def Recursion(parentPart:Part, partBuffer:ArrayBuffer[PartsListBean], opt:Int):Unit = {
	  for(child <- parentPart.parts) {
	    	if(parentPart.partRelation(child.id).delDcId==0) {
	    		if(opt!=3 || opt==3 && child.name.startsWith("Unit")) {
	    			partBuffer += PartsListBean(parentPart.name, child.name, parentPart.partRelation(child.id).quantity)
	    		}
	    		if(opt==1 || opt==2 && !child.name.startsWith("Part") || opt==3) {
	    			Recursion(child, partBuffer, opt)
	    		}
	    	}
	  }
	}

	def UpRecursion(childPart:Part, partBuffer:ArrayBuffer[PartsListBean], opt:Int):Unit = {
	  if(childPart.parentParts.size == 0 && opt == 2) {
	    partBuffer += PartsListBean("", childPart.name,0)
	  }
	  for(parent <- childPart.parentParts) {
		  if(parent.partRelation(childPart.id).delDcId == 0 ) {
			  if(opt != 2) {
				  partBuffer += PartsListBean(childPart.name, parent.name, parent.partRelation(childPart.id).quantity)
			  }
			  if(opt != 1) {
				  UpRecursion(parent, partBuffer, opt)
			  }
		  }
	  }
	}

	def createRelation(parent:String) = Action {implicit request =>
	  Ok(views.html.createRelationForm(relationForm.fill(new PartsListBean(parent, "", 0)),""))
	}
	
	def updateRelation(parentNo:String, childNo:String) = Action { implicit request =>
	  inTransaction {
		  Ok(views.html.updateRelationForm(relationForm.fill(generatePartsListBean(parentNo, childNo)), childNo))
	  }
	}
	
	def relationRegistration() = Action { implicit request =>
	  relationForm.bindFromRequest.fold(
	      formWithErrors => BadRequest(views.html.createRelationForm(formWithErrors, "")),
	   data => {
		   inTransaction {
		     // 子品番正展開配列
		     var partBuffer = ArrayBuffer[PartsListBean]()
		     for (parentPart <- PartsListDb.parts.where(p => p.name === data.child )) {
				 Recursion(parentPart, partBuffer, 1)
	   		  }
		     // 親品番逆展開配列
		     var upPartBuffer = ArrayBuffer[PartsListBean]()
		     for (childPart <- PartsListDb.parts.where(p => p.name === data.parent)) {
		    	 UpRecursion(childPart, upPartBuffer, 0)
		      }
		     var message:String = null
		     // 部品表ループチェック
		     // 親品番＝子品番 の場合エラー
		     if(data.child.equals(data.parent)) {
		       message = Messages("form.error1")
		     } else {
		         // 子品番=親品番の逆展開 の場合エラー
		    	 for(upPart <- upPartBuffer ) {
		    		 if(upPart.child.equals(data.child)) {
		    			 message = Messages("form.error1")
		    		 }
		    	 }
		    	 // 子品番の正展開=親品番の逆展開 の場合エラー
		    	 for(chPart <- partBuffer) {
		    	   for(upPart <- upPartBuffer) {
		    	     if(upPart.child.equals(chPart.child)) {
		    			 message = Messages("form.error1")
		    	     }
		    	   }
		    	 }
		     }
		    if(message == null) {
			  val pr = getPart(data.parent).parts.associate(getPart(data.child))
			  pr.quantity = data.quantity
			  PartsListDb.partRelations.update(pr)
			  Home.flashing("success" -> "Relation %s has been created".format(data.parent))
		    } else {
	         Ok(views.html.createRelationForm(relationForm.fill(data), message))
		    }
		   }
	  }
     )
	}
	
	def relationUpdate(childName:String) = Action { implicit request =>
	  relationForm.bindFromRequest.fold(
		   formWithErrors => BadRequest(views.html.updateRelationForm(formWithErrors, null)),
	   data => {
	     if(data.child == childName) {
	       	//PartRelation データ更新処理
		   		inTransaction {
		   			val pr = getPart(data.parent).parts.assign(getPart(data.child))
		   			pr.quantity = data.quantity
		   			PartsListDb.partRelations.update(pr)
		   			Home.flashing("success" -> "Relation %s has been created".format(data.parent))
		   		} 
	     } else {
		   		//PartRelation キー情報（ChildId）の更新なので削除／登録処理
	    	 	inTransaction {
	    	 		PartsListDb.partRelations.deleteWhere(tpr => tpr.parentId === getPart(data.parent).id 
	    	 		    and tpr.childId === getPart(childName).id)
	    	 		val pr = getPart(data.parent).parts.associate(getPart(data.child))
	    	 		pr.quantity = data.quantity
	    	 		PartsListDb.partRelations.update(pr)
		   			Home.flashing("success" -> "Relation %s has been created".format(data.parent))
	    	 	}
	     }
	   }
	  )
	}
	
	def relationDelete(parentName:String, childName:String) = Action {
	  inTransaction {
	    val parent = getPart(parentName)
	    val child = getPart(childName)
	    PartsListDb.partRelations.deleteWhere(pl => pl.parentId === parent.id and pl.childId === child.id)
	    Home.flashing("success" -> "Relation %s has been deleted".format(parent.name + "/" + child.name))
	  }
	}
	
	def designChangeForm(parentName:String, childName:String) = Action { implicit request =>
	      	inTransaction {
	      	  val designChangeRelationForm = DesignChangeRelationForm(generatePartsListBean(parentName, childName), generatePartsListBean(parentName, childName), "")
	      		Ok(views.html.designChangeRelationForm(designChangeRegistForm.fill(designChangeRelationForm)))
	      	}
	}
	
	def designChange() = Action { implicit request =>
	  designChangeRegistForm.bindFromRequest.fold(
	      formWithErrors => BadRequest(views.html.designChangeRelationForm(formWithErrors)),
	      data => {
	    	  inTransaction {
	    		  val dc = PartsListDb.designChanges.where(dc => dc.dcNo === data.dcno).head
	    		  val parent = getPart(data.partsListBeanBefore.parent)
	    		  if(!data.partsListBeanBefore.child.isEmpty()) {
	    			  val delRelation = parent.parts.assign(getPart(data.partsListBeanBefore.child))
	    			  dc.delPartRelation.assign(delRelation)
	    			  PartsListDb.partRelations.update(delRelation)
	    		  }
	    		  if(!data.partsListBeanAfter.child.isEmpty()) {
	    			  val addRelation = parent.parts.associate(getPart(data.partsListBeanAfter.child))
	    			  dc.addPartRelation.associate(addRelation)
	    			  addRelation.quantity = data.partsListBeanAfter.quantity
	    			  PartsListDb.partRelations.update(addRelation)
	    		  }
	    		  Home.flashing("success" -> "Relation %s has been changed".format(data.partsListBeanBefore.parent + "/" + data.partsListBeanBefore.child))
	    	  }
	      }
	  )
	}
	
	def getPart(partNo:String):Part =  {
		  PartsListDb.parts.where(p => p.name === partNo).head
	}
	
	def generatePartsListBean(parentNo:String, childNo:String):PartsListBean = {
	  if(childNo.isEmpty()) {
	      PartsListBean(parentNo, childNo, 0)
	  } else {
		  PartsListBean(parentNo, childNo, getPart(parentNo).partRelation(getPart(childNo).id).quantity)
	  }
	}

}