package controllers

import mvc.AuthAction
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 models._
import models.services._
import models.services.impl._
import beans._
import forms._
import controllers.services._
import models.services._
import scala.collection.immutable.Map
import scala.collection.immutable.Seq
import scala.collection.mutable.ArrayBuffer
import com.google.inject._
import modules._

object PartsListController extends Controller{
  val inject = Guice.createInjector(new ServiceModules)
  val projectManager = inject.getInstance(classOf[ProjectManager])
  val Home = Redirect(routes.PartsListController.index(0,0,"",""))
  val Home2 = Redirect(routes.PartsListController.relationRegistration(""))
  val relationForm = Form(
       mapping(
           "parent" -> nonEmptyText,
           "child" -> nonEmptyText,
           "quantity" -> longNumber,
           "relationKey" -> text
        )(PartsListBean.apply)(PartsListBean.unapply)
    )
    
	def index(opt:Int, page:Int, key:String, relationKey:String) = AuthAction {
     Action { implicit request =>
      if(request == null) {
         Ok(views.html.errors.errorNotAuthentication())
       } else {
         inTransaction{
           val partsBuffer = PartsList().getPartsBuffer(opt, page, key, relationKey)
           var totalCost:Long =0
           for(partBuffer <- partsBuffer) {
             totalCost += partBuffer.cost
             }
           val row = Integer.decode(Messages("list.row"))
           Ok(views.html.partslistshow(partsBuffer.drop(page*row).take(row), opt, page, partsBuffer.size, key, totalCost, relationKey))
           }
        }
      }
    }
   
	def downLoad(opt:Int, page:Int, key:String, relationKey:String) = AuthAction {
     Action { implicit request =>
      if(request == null) {
         Ok(views.html.errors.errorNotAuthentication())
       } else {
         inTransaction{
           val partsBuffer = PartsList().getPartsBuffer(opt, page, key, relationKey)
           var totalCost:Long =0
           for(partBuffer <- partsBuffer) {
             totalCost += partBuffer.cost
             }
           val attachment = "attachment; filename=" + key + "_download.csv"
           Ok(views.html.partsListsCsv(partsBuffer)).withHeaders(CONTENT_DISPOSITION -> attachment).as("text/csv")
           }
        }
      }
    }

	def matrixPartList(project: String) = AuthAction {
     Action { implicit request =>
       if(request == null) {
         Ok(views.html.errors.errorNotAuthentication())
       } else {
         var partsListBeans = Seq[Seq[PartsListShowBean]]()
         var allChildren = Seq[Part]()
         var matrixPartsListBeans = Map[Part, Seq[beans.MultiPartsListBean]]()
         inTransaction {
           if(project != "") {
             val models = projectManager.getByName(project).parts
               //  各モデルに対し、部品表抽出処理を実施。
             for(model <- models) {
                 // 部品表の１レベル展開。
               val partsListBean = PartsList().getPartsBuffer(0, 0, model.name, "")
                 // 全ての部品表配列を蓄積。
               if(partsListBean.size != 0) {
                 partsListBeans = partsListBeans.:+(partsListBean)
               } else {
                 // partsListBean が0件の場合、空の部品表配列を蓄積。空リストを表示するため
                 partsListBeans = partsListBeans.:+(Seq(PartsListShowBean(model.name, Part("", null, 0, 0), 0, "", 0)))
                 }
               }
               // 部品表配列より全ての子部品を蓄積。
             for(partsListBean <- partsListBeans) {
               for(partsList <- partsListBean) {
                    //　子品番がブランクは、空リストを表示するためのダミー配列なので、子品番蓄積からは除外。
                 if(partsList.child.name!="") {
                   allChildren = allChildren.:+(partsList.child)
                   }
                 }
               }
             matrixPartsListBeans = PartsList().getMatrixPartsList(partsListBeans, allChildren)
             Ok(views.html.matrixpartslistshow(allChildren.distinct, matrixPartsListBeans, allChildren.distinct.size, models, project))
           } else {
             Ok(views.html.matrixpartslistshow(allChildren.distinct, matrixPartsListBeans, allChildren.distinct.size, null, project))
             }
         }
       }
     }
   }

   def upIndex(opt:Int, page:Int, key:String) = AuthAction {
	  Action { implicit request =>
	    if(request == null) {
         Ok(views.html.errors.errorNotAuthentication())
	    } else {
	       var partBuffer = Seq[PartsListBean]()
	       inTransaction {
	         for (childPart <- PartManager().getByLikeName(key)) {
	           for(returnPartBuffer <- PartRecursion().up(childPart, opt)) {
	             partBuffer = partBuffer.:+(returnPartBuffer)
	             }
	           }
	         }
	       val row = Integer.decode(Messages("list.row"))
	       Ok(views.html.uppartslistshow(partBuffer.drop(page*row).take(row), opt, page, partBuffer.size, key))
	     }
	  }
	}
	
	def createRelation(parent:String, child:String, project:String) = AuthAction {
	  Action {implicit request =>
	    if(request == null) {
         Ok(views.html.errors.errorNotAuthentication())
	    } else{
	      Ok(views.html.createRelationForm(relationForm.fill(new PartsListBean(parent, child, 0, "")),project, ""))
	    }
	  }
	}
	
	def updateRelation(parentNo:String, childNo:String, project:String) = AuthAction {
	  Action { implicit request =>
	    if(request == null) {
         Ok(views.html.errors.errorNotAuthentication())
	    } else {
	      inTransaction {
	        Ok(views.html.updateRelationForm(relationForm.fill(generatePartsListBean(parentNo, childNo)), childNo, project, ""))
	       }
	    }
	  }
	}
	
	def relationRegistration(project:String) = Action { implicit request =>
	  relationForm.bindFromRequest.fold(
	      formWithErrors => BadRequest(views.html.createRelationForm(formWithErrors, "", "")),
	   data => {
		   inTransaction {
		    val message = PartRelationManager().insert(data, null, 0)
		    if( message == null) {
		      if(project=="") {
		    	  Home.flashing("success" -> "Relation %s has been created".format(data.parent))
		      } else {
	        	 Redirect(routes.PartsListController.matrixPartList(project))
		      }
		    } else {
	         Ok(views.html.createRelationForm(relationForm.fill(data), "", message))
		    }
		   }
	  }
     )
	}
	
	def relationUpdate(childName:String, project:String) = Action { implicit request =>
	  relationForm.bindFromRequest.fold(
		   formWithErrors => BadRequest(views.html.updateRelationForm(formWithErrors, null, "", "")),
	   data => {
	     inTransaction {
	       val message = PartRelationManager().update(data, childName)
	       if(message == null) {
	         if(project=="") {
	        	 Home.flashing("success" -> "Relation %s has been created".format(data.parent))
	         } else {
	        	 Redirect(routes.PartsListController.matrixPartList(project))
	          }
	        } else {
	          Ok(views.html.updateRelationForm(relationForm.fill(data), childName, project, message))
	        }
	      }
	    }
	  )
	}
	
	def relationDelete(parentName:String, childName:String) = AuthAction {
	  Action {implicit request =>
	    if(request == null) {
         Ok(views.html.errors.errorNotAuthentication())
	    } else {
	      inTransaction {
	        val data = PartsListBean(parentName, childName, 0, "")
	        PartRelationManager().delete(data, childName)
	        Home.flashing("success" -> "Relation %s has been deleted".format(parentName + "/" + childName))
	        }
	    }
	  }
	}
	
	def generatePartsListBean(parentNo:String, childNo:String):PartsListBean = {
	  val pr = PartManager().getByName(parentNo).head.partRelation(PartManager().getByName(childNo).head.id)
	  if(childNo.isEmpty()) {
	      PartsListBean(parentNo, childNo, 0, pr.relationKey)
	  } else {
		  PartsListBean(parentNo, childNo, pr.quantity, pr.relationKey)
	  }
	}
	
}