import org.codehaus.groovy.grails.plugins.springsecurity.Secured

@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_TaskManager', 'ROLE_TaskUser'])
class EntryDetailedController extends BaseController {

    def authService
    def taskService

    def index = { redirect(action:list,params:params) }

    // the delete, save and update actions only accept POST requests
    static allowedMethods = [delete:'POST', save:'POST', update:'POST', ajaxCreate:'POST', ajaxSave:'POST']

    def list = {
        if(!params.max) params.max = 10
        [ entryInstanceList: Entry.list( params ) ]
    }

    def show = {
        def entryInstance = Entry.get( params.id )

        if(!entryInstance) {
            flash.message = "Entry not found with id ${params.id}"
            redirect(controller: 'taskDetailed', action: 'search')
        }
        else { return [ entryInstance : entryInstance ] }
    }

    def delete = {
        def entryInstance = Entry.get( params.id )
        if(entryInstance) {
            if(entryInstance.enteredBy.loginName == authService.currentUser.loginName) {
                def taskId = entryInstance.task.id
                entryInstance.delete(flush:true)
                flash.message = "Entry ${params.id} deleted"
                redirect(controller: 'taskDetailed', action: 'show', id: taskId)
            }
            else {
                flash.message = "You may only delete your own entries."
                redirect(action:show,id:entryInstance.id)
            }

        }
        else {
            flash.message = "Entry not found with id ${params.id}"
            redirect(controller: "taskDetailed", action:"search")
        }
    }

    def edit = {
        def entryInstance = Entry.get( params.id )
        if(!entryInstance) {
                flash.message = "Entry not found with id ${params.id}"
                redirect(controller: "taskDetailed", action:"search")
        }
        else {

            if(entryInstance.enteredBy.loginName == authService.currentUser.loginName) {
                return [ entryInstance : entryInstance ]
            }
            else {
                flash.message = "You may only edit your own entries."
                redirect(action:show,id:entryInstance.id)
            }

        }
    }

    /// @todo: Refactor to taskService and include moving task to "In Progress" when Entry.duration is updated.
    def update = {
        def entryInstance = Entry.get( params.id )
        if(entryInstance) {
            // The update method only accepts post requests, so this is just in case.
            if(entryInstance.enteredBy.loginName == authService.currentUser.loginName) {
                entryInstance.properties = params
                if(!entryInstance.hasErrors() && entryInstance.save(flush: true)) {
                    // If PM Entry update task.highestSeverity
                    if(entryInstance.entryType.id == 6) {
                        def clist = []
                        entryInstance.task.entries.each { entry ->
                            if(entry.entryType.id == 6)
                                clist << entry.highestSeverity
                        }

                        if(clist)
                            entryInstance.task.highestSeverity = clist.sort{p1,p2 -> p2.id <=> p1.id}[0]
                    }
                    flash.message = "Entry ${params.id} updated"
                    redirect(action:show,id:entryInstance.id)
                }
                else {
                    render(view:'edit',model:[entryInstance:entryInstance])
                }
            }
            else {
                flash.message = "You may only edit your own entries."
                redirect(action:show,id:entryInstance.id)
            }
        }
        else {
            flash.message = "Entry not found with id ${params.id}"
            redirect(controller: "taskDetailed", action:"search")
        }
    }

    def ajaxCreate = {
        if(!params.taskId || !params.entryTypeId) {
            params.errorMessage = g.message(code: "entry.create.no.params.ajax")
            render(contentType:"text/json", status: 403, template: "/shared/messages")
            return
        }

        def taskInstance = Task.read(params.taskId)

        def entryInstance = new Entry()
        entryInstance.task = taskInstance
        entryInstance.entryType = EntryType.read(params.entryTypeId)

        // Check if we should create this entry.
        def checkResult = taskService.checkCreateEntry(entryInstance)
        if(checkResult.error) {
            params.errorMessage = g.message(code: checkResult.error.code)
            render(contentType:"text/json", status: 403, template: "/shared/messages")
            return
        }

        // Success.
        def model = ['entryInstance': entryInstance]

        render(contentType:"text/json") {
            updates = array {
                element([ mode: 'replace', target:"$params.target", content: g.render(template: 'create', model:model) ])
            }
        }

    } // ajaxCreate

    def ajaxSave = {
        def result = taskService.saveEntry(params)

        // Success.
        if(!result.error) {
            def entryList = Entry.withCriteria {
                                            eq("entryType", result.entryInstance.entryType)
                                            task {
                                                idEq(result.taskId)
                                            }
                                    }

            def taskInstance = entryList[0].task
            def taskModificationList = TaskModification.findAllByTask(taskInstance, [max:100, sort:"id", order:"asc"])
            def model = ['entryList': entryList]
            def taskModel = ['taskInstance': taskInstance]
            def taskModificationModel = ['taskModificationList': taskModificationList ]

            render(contentType:"text/json") {
                updates = array {
                    element([ mode: 'replace', target:"$params.target", content: g.render(template: 'list', model:model) ])
                    element([ mode: 'replace',
                                    target:".tabHeader",
                                    content: g.render(template: '/taskDetailed/showTabHeader', model:taskModel) ])
                    element([ mode: 'replace',
                                    target:"#taskControlButtons",
                                    content: g.render(template: '/taskDetailed/showTaskControlButtons', model:taskModel) ])
                    element([ mode: 'replace',
                                    target:"#modifications",
                                    content: g.render(template: '/taskDetailed/showTaskModifications', model:taskModificationModel) ])
                }
            }
            return
        } // Success.

        if(result.error.code != "default.create.failure")
            params.errorMessage = g.message(code: result.error.code)

        def model = ['entryInstance': result.entryInstance]
        render(contentType:"text/json", status: 403, template: "create", model: model)
    } // ajaxSave

    def create = {
        if(!params.taskInstance?.id || !params.entryType?.id) {
            flash.message = g.message(code:"entry.create.no.params")
            redirect(controller:"taskDetailed", action:"search")
            return
        }

        def taskInstance = Task.read(params.taskInstance.id)

        if(!taskInstance) {
            flash.message = g.message(code:"task.notFound")
            redirect(controller:"taskDetailed", action:"search")
            return
        }

        // Check for Complete task.
        if(taskInstance.taskStatus.id == 3) {
            flash.errorMessage = g.message(code:"task.operationNotPermittedOnCompleteTask")
            redirect(controller:"taskDetailed", action:"show", id: taskInstance.id)
            return
        }

        def entryInstance = new Entry()
        entryInstance.task = taskInstance
        entryInstance.entryType = EntryType.read(params.entryType.id)
        return ['entryInstance': entryInstance]
    } // create

    def save = {
        def result = taskService.saveEntry(params)

        if(!result.error) {
            flash.message = "Entry created."
            redirect(controller: "taskDetailed", action: "show", id: result.taskId)
            return
        }

        if(result.error.code != "default.create.failure") {
            params.errorMessage = g.message(code: result.error.code)
        }

        render(view:'create',model:[entryInstance: result.entryInstance])
    } // save

} // end class
