class TaskService {

    boolean transactional = false

    def dateUtilService
    def personService

    def create(params) {
        Task.withTransaction { status ->
            def result = [:]
            // Default status to "not started" if not supplied.
            params.taskStatus = params.taskStatus ?: TaskStatus.get(1)
            def taskInstance = new Task(params)
            result.taskInstance = taskInstance

            if(taskInstance.save()) {
                def taskModification = new TaskModification(person: personService.currentUser(),
                                                        taskModificationType: TaskModificationType.get(1),
                                                        task: taskInstance)

                if(!taskModification.save()) {
                    status.setRollbackOnly()
                    taskInstance.errors.rejectValue("taskModifications", "task.modifications.failedToSave")
                    result.error = true
                    return result
                }

                return result
            }
            else {
                result.error = true
                return result
            }

        } //end withTransaction
    } // end create()

    def createEntry(params) {
        Task.withTransaction { status ->
            def result = [:]
            result.entryInstance = new Entry(params)
            result.entryInstance.enteredBy = personService.currentUser()

            if(result.entryInstance.validate()) {
                def taskInstance = Task.lock(result.entryInstance.task.id)
                result.taskId = result.entryInstance.task.id

                if(!taskInstance) {
                    status.setRollbackOnly()
                    result.entryInstance.errors.rejectValue('task', "entry.task.notFound")
                    result.error = true
                    return result
                }

                if(taskInstance.taskStatus.id == 3) {
                    status.setRollbackOnly()
                    result.entryInstance.errors.rejectValue('task', "entry.task.taskIsComplete")
                    result.error = true
                    return result
                }

                // If task status is "Not Started" and entry type is "Work Done" then we create the started modification and set the status.
                if(taskInstance.taskStatus.id == 1 && result.entryInstance.entryType.id == 2) {

                    // Create the "Started" task modification, this provides the "Actual started date".
                    def taskModification = new TaskModification(person: personService.currentUser(),
                                                            taskModificationType: TaskModificationType.get(2),
                                                            task: taskInstance)

                    if(!taskModification.save()) {
                        status.setRollbackOnly()
                        taskInstance.errors.rejectValue("task", "entry.task.failedToSaveTaskModification")
                        result.error = true
                        return result
                    }

                    // Set task status to "In progress".
                    taskInstance.taskStatus = TaskStatus.get(2)

                    if(!taskInstance.save()) {
                        status.setRollbackOnly()
                        result.entryInstance.errors.rejectValue("task", "entry.task.failedToSave")
                        result.error = true
                        return result
                    }
                }

                if(!result.entryInstance.save()) {
                    status.setRollbackOnly()
                    result.error = true
                    return result
                }

                // All went well if we get to here.
                return result
            }
            else {
                result.error = true
                return result
            }

        } //end withTransaction
    } // end create()

    def update(params) {
        Task.withTransaction { status ->
            def result = [:]
            result.taskInstance = Task.get(params.id)
            if(result.taskInstance) {

                // Optimistic locking check.
                if(params.version) {
                    def version = params.version.toLong()
                    if(result.taskInstance.version > version) {
                        status.setRollbackOnly()
                        result.taskInstance.errors.rejectValue("version", "task.optimistic.locking.failure", "Another user has updated this Task while you were editing.")
                        result.error = true
                        return result
                    }
                }

                result.taskInstance.properties = params

                if(result.taskInstance.save()) {
                    def taskModification = new TaskModification(person:personService.currentUser(),
                                                            taskModificationType: TaskModificationType.get(3),
                                                            task: result.taskInstance)
                    if(taskModification.save()) {
                        // All went well.
                        return result
                    }
                    else {
                        status.setRollbackOnly()
                        result.taskInstance.errors.rejectValue("taskModifications", "task.modifications.failedToSave")
                        result.error = true
                        return result
                    }
                }
            }
            // Something failed.
            status.setRollbackOnly()
            result.error = true
            return result

        } //end withTransaction
    }  // end update()

    def complete(params) {
        Task.withTransaction { status ->
            def result = [:]
            result.taskInstance = Task.get(params.id)
            if(result.taskInstance) {

                // Optimistic locking check.
                if(params.version) {
                    def version = params.version.toLong()
                    if(result.taskInstance.version > version) {
                        status.setRollbackOnly()
                        result.taskInstance.errors.rejectValue("version", "task.optimistic.locking.failure", "Another user has updated this Task while you were editing.")
                        result.error = true
                        return result
                    }
                }

                result.taskInstance.taskStatus = TaskStatus.get(3)

                if(result.taskInstance.save()) {
                    def taskModification = new TaskModification(person:personService.currentUser(),
                                                            taskModificationType: TaskModificationType.get(4),
                                                            task: result.taskInstance)
                    if(taskModification.save()) {
                        // All went well.
                        return result
                    }
                    else {
                        status.setRollbackOnly()
                        result.taskInstance.errors.rejectValue("taskModifications", "task.modifications.failedToSave")
                        result.error = true
                        return result
                    }
                }
            }
            // Something failed.
            status.setRollbackOnly()
            result.error = true
            return result

        } //end withTransaction
    }  // end complete()

    def reopen(params) {
        Task.withTransaction { status ->
            def result = [:]
            result.taskInstance = Task.get(params.id)
            if(result.taskInstance) {

                // Optimistic locking check.
                if(params.version) {
                    def version = params.version.toLong()
                    if(result.taskInstance.version > version) {
                        status.setRollbackOnly()
                        result.taskInstance.errors.rejectValue("version", "task.optimistic.locking.failure", "Another user has updated this Task while you were editing.")
                        result.error = true
                        return result
                    }
                }

                result.taskInstance.taskStatus = TaskStatus.get(2)

                if(result.taskInstance.save()) {
                    def taskModification = new TaskModification(person:personService.currentUser(),
                                                            taskModificationType: TaskModificationType.get(5),
                                                            task: result.taskInstance)
                    if(taskModification.save()) {
                        // All went well.
                        return result
                    }
                    else {
                        status.setRollbackOnly()
                        result.taskInstance.errors.rejectValue("taskModifications", "task.modifications.failedToSave")
                        result.error = true
                        return result
                    }
                }
            }
            // Something failed.
            status.setRollbackOnly()
            result.error = true
            return result

        } //end withTransaction
    }  // end reopen()

    def trash(params) {
        Task.withTransaction { status ->
            def result = [:]
            result.taskInstance = Task.get(params.id)
            if(result.taskInstance) {

                // Optimistic locking check.
                if(params.version) {
                    def version = params.version.toLong()
                    if(result.taskInstance.version > version) {
                        status.setRollbackOnly()
                        result.taskInstance.errors.rejectValue("version", "task.optimistic.locking.failure", "Another user has updated this Task while you were editing.")
                        result.error = true
                        return result
                    }
                }

                result.taskInstance.trash = true

                if(result.taskInstance.save()) {
                    def taskModification = new TaskModification(person:personService.currentUser(),
                                                            taskModificationType: TaskModificationType.get(6),
                                                            task: result.taskInstance)
                    if(taskModification.save()) {
                        // All went well.
                        return result
                    }
                    else {
                        status.setRollbackOnly()
                        result.taskInstance.errors.rejectValue("taskModifications", "task.modifications.failedToSave")
                        result.error = true
                        return result
                    }
                }
            }
            // Something failed.
            status.setRollbackOnly()
            result.error = true
            return result

        } //end withTransaction
    }  // end trash()

    def restore(params) {
        Task.withTransaction { status ->
            def result = [:]
            result.taskInstance = Task.get(params.id)
            if(result.taskInstance) {

                // Optimistic locking check.
                if(params.version) {
                    def version = params.version.toLong()
                    if(result.taskInstance.version > version) {
                        status.setRollbackOnly()
                        result.taskInstance.errors.rejectValue("version", "task.optimistic.locking.failure", "Another user has updated this Task while you were editing.")
                        result.error = true
                        return result
                    }
                }

                result.taskInstance.trash = false

                if(result.taskInstance.save()) {
                    def taskModification = new TaskModification(person:personService.currentUser(),
                                                            taskModificationType: TaskModificationType.get(7),
                                                            task: result.taskInstance)
                    if(taskModification.save()) {
                        // All went well.
                        return result
                    }
                    else {
                        status.setRollbackOnly()
                        result.taskInstance.errors.rejectValue("taskModifications", "task.modifications.failedToSave")
                        result.error = true
                        return result
                    }
                }
            }
            // Something failed.
            status.setRollbackOnly()
            result.error = true
            return result

        } //end withTransaction
    }  // end restore()

    def approve(params) {
        Task.withTransaction { status ->
            def result = [:]
            result.taskInstance = Task.get(params.id)
            if(result.taskInstance) {

                // Optimistic locking check.
                if(params.version) {
                    def version = params.version.toLong()
                    if(result.taskInstance.version > version) {
                        status.setRollbackOnly()
                        result.taskInstance.errors.rejectValue("version", "task.optimistic.locking.failure", "Another user has updated this Task while you were editing.")
                        result.error = true
                        return result
                    }
                }

                result.taskInstance.approved = true

                if(result.taskInstance.save()) {
                    def taskModification = new TaskModification(person:personService.currentUser(),
                                                            taskModificationType: TaskModificationType.get(8),
                                                            task: result.taskInstance)
                    if(taskModification.save()) {
                        // All went well.
                        return result
                    }
                    else {
                        status.setRollbackOnly()
                        result.taskInstance.errors.rejectValue("taskModifications", "task.modifications.failedToSave")
                        result.error = true
                        return result
                    }
                }
            }
            // Something failed.
            status.setRollbackOnly()
            result.error = true
            return result

        } //end withTransaction
    }  // end approve()

    def renegeApproval(params) {
        Task.withTransaction { status ->
            def result = [:]
            result.taskInstance = Task.get(params.id)
            if(result.taskInstance) {

                // Optimistic locking check.
                if(params.version) {
                    def version = params.version.toLong()
                    if(result.taskInstance.version > version) {
                        status.setRollbackOnly()
                        result.taskInstance.errors.rejectValue("version", "task.optimistic.locking.failure", "Another user has updated this Task while you were editing.")
                        result.error = true
                        return result
                    }
                }

                result.taskInstance.approved = false

                if(result.taskInstance.save()) {
                    def taskModification = new TaskModification(person:personService.currentUser(),
                                                            taskModificationType: TaskModificationType.get(9),
                                                            task: result.taskInstance)
                    if(taskModification.save()) {
                        // All went well.
                        return result
                    }
                    else {
                        status.setRollbackOnly()
                        result.taskInstance.errors.rejectValue("taskModifications", "task.modifications.failedToSave")
                        result.error = true
                        return result
                    }
                }
            }
            // Something failed.
            status.setRollbackOnly()
            result.error = true
            return result

        } //end withTransaction
    }  // end renegeApproval()

} // end TaskService
