/**
* Provides a service class for the TaskProcedure domain class.
*/
class TaskProcedureService {

    boolean transactional = false

    def authService

    /**
    * Updates an existing taskProcedure.
    * @param params The params to update for taskProcedure with id of params.id.
    * @returns A map containing result.error (if any error) and result.taskProcedureInstance (if available).
    */
    def update(params) {
        TaskProcedure.withTransaction { status ->
            def result = [:]

            def fail = { Map m ->
                status.setRollbackOnly()
                if(result.taskProcedureInstance && m.field)
                    result.taskProcedureInstance.errors.rejectValue(m.field, m.code)
                result.error = [ code: m.code, args: ["TaskProcedure", params.id] ]
                // Fetch to prevent lazy initialization error.
                result.taskProcedureInstance?.linkedTask.primaryAsset
                result.taskProcedureInstance?.createdBy
                return result
            }

            result.taskProcedureInstance = TaskProcedure.get(params.id)

            if(!result.taskProcedureInstance)
                return fail(code:"default.not.found")

            // Optimistic locking check.
            if(params.version) {
                if(result.taskProcedureInstance.version > params.version.toLong())
                    return fail(field:"version", code:"default.optimistic.locking.failure")
            }

            result.taskProcedureInstance.properties = params
            result.taskProcedureInstance.lastUpdatedBy = authService.currentUser
            result.taskProcedureInstance.lastUpdated = new Date() // Required to trigger version increment.

            // Gaps in the html index's can be created by adding 2 items and removing the first one.
            // This creates a gap at the missing index where LazyList will return a null.
            def nullMaintenanceActions = result.taskProcedureInstance.maintenanceActions.findAll {!it}
            if (nullMaintenanceActions) {
                result.taskProcedureInstance.maintenanceActions.removeAll(nullMaintenanceActions)
            }
            def nullDocumentReferences = result.taskProcedureInstance.documentReferences.findAll {!it}
            if (nullDocumentReferences) {
                result.taskProcedureInstance.documentReferences.removeAll(nullDocumentReferences)
            }

            // Save for restoration if validation fails.
            def savedMaintenanceActions = new ArrayList(result.taskProcedureInstance.maintenanceActions)
            def savedDocumentReferences = new ArrayList(result.taskProcedureInstance.documentReferences)

            // Remove toBeDeleted before validation.
            def ma_toBeDeleted = result.taskProcedureInstance.maintenanceActions.findAll {it.toBeDeleted}
            if (ma_toBeDeleted) {
                result.taskProcedureInstance.maintenanceActions.removeAll(ma_toBeDeleted)
            }
            def docRef_toBeDeleted = result.taskProcedureInstance.documentReferences.findAll {it.toBeDeleted}
            if (docRef_toBeDeleted) {
                result.taskProcedureInstance.documentReferences.removeAll(docRef_toBeDeleted)
            }

            if(result.taskProcedureInstance.hasErrors() || !result.taskProcedureInstance.save()) {
                // Restore the saved items, some of which contain toBeDeleted flags but
                // have not been deleted yet since validation failed.
                // The toBeDeleted items are hidden in the view.
                result.taskProcedureInstance.maintenanceActions = savedMaintenanceActions
                result.taskProcedureInstance.documentReferences = savedDocumentReferences
                // Populate collection errors for display.
                result.taskProcedureInstance.maintenanceActions.each { it.validate() }
                result.taskProcedureInstance.documentReferences.each { it.validate() }
                return fail(code:"default.update.failure")
            }

            // Success.
            return result

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

    /**
    * Creates a new taskProcedure with the given params.
    * @param params The params to use when creating the new taskProcedure.
    * @returns A map containing result.error (if any error) and result.taskProcedure.
    */
    def save(params) {
        def result = [:]
        TaskProcedure.withTransaction { status ->
            def fail = { Map m ->
                status.setRollbackOnly()
                if(result.taskProcedureInstance && m.field) 
                    result.taskProcedureInstance.errors.rejectValue(m.field, m.code)
                result.error = [ code: m.code, args: ["TaskProcedure", params.id] ]
                // Fetch to prevent lazy initialization error.
                result.taskProcedureInstance.linkedTask.primaryAsset
                return result
            }

            result.taskProcedureInstance = new TaskProcedure(params)

            // Optimistic locking check on linkedTask.
            if(result.taskProcedureInstance.linkedTask.taskProcedure)
                    return fail(field:"version", code:"default.optimistic.locking.failure")

            result.taskProcedureInstance.createdBy = authService.currentUser
            result.taskProcedureInstance.lastUpdatedBy = authService.currentUser

            // Gaps in the html index's can be created by adding 2 items and removing the first one.
            // This creates a gap at the missing index where LazyList will return a null.
            def nullMaintenanceActions = result.taskProcedureInstance.maintenanceActions.findAll {!it}
            if (nullMaintenanceActions) {
                result.taskProcedureInstance.maintenanceActions.removeAll(nullMaintenanceActions)
            }
            def nullDocumentReferences = result.taskProcedureInstance.documentReferences.findAll {!it}
            if (nullDocumentReferences) {
                result.taskProcedureInstance.documentReferences.removeAll(nullDocumentReferences)
            }

            // Also sets: taskInstance.taskProcedure = taskProcedureInstance
            result.taskProcedureInstance.addToTasks(result.taskProcedureInstance.linkedTask)

            if(result.taskProcedureInstance.hasErrors() || !result.taskProcedureInstance.save()) {
                // Populate collection errors for display.
                result.taskProcedureInstance.maintenanceActions.each { it.validate() }
                result.taskProcedureInstance.documentReferences.each { it.validate() }
                return fail(code:"default.create.failure")
            }

        } //end withTransaction

        result.taskProcedureInstance.lastUpdated = new Date() // Required to trigger version increment to 1.

        // success
        return result
    }  // end save()

} // end class
