/**
* Provides a service class for the InventoryItem domain class.
*/
class InventoryItemService {

    boolean transactional = false

    /**
    * Prepare a sorted list of possible alternateItems.
    */
    def getPossibleAlternateItems(inventoryItemInstance) {
        def criteria = inventoryItemInstance.createCriteria()
        def possibleAlternateItems = criteria {
            and {
                eq('isActive', true)
                notEqual('id', inventoryItemInstance.id)
            }
        }.sort { p1, p2 -> p1.name.compareToIgnoreCase(p2.name) }
    }

    /**
    * Prepare the data for the show view.
    * The result can be used to easily construct the model for the show view.
    * @param params The incoming params as normally passed to the show view
    * primarily including the id of the inventoryItem.
    * @returns A map containing result.error, if any error, otherwise result.inventoryItemInstance.
    */
    def show(params) {
        def result = [:]
        def fail = { Map m ->
            result.error = [ code: m.code, args: ["InventoryItem", params.id] ]
            return result
        }

        result.inventoryItemInstance = InventoryItem.get( params.id )

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

        result.showTab = [:]
        switch (params.showTab) {
            case "showDetailTab":
                result.showTab.detail =  new String("true")
                break
            case "showMovementTab":
                result.showTab.movement =  new String("true")
                break
            default:
                result.showTab.inventory = new String("true")
        }

        def p = [:]
        p.max = result.inventoryMovementListMax = 10
        p.order = "desc"
        p.sort = "id"
        result.inventoryMovementList = InventoryMovement.findAllByInventoryItem(result.inventoryItemInstance, p)
        result.inventoryMovementListTotal = InventoryMovement.countByInventoryItem(result.inventoryItemInstance)

        // Success.
        return result

    } // end show()

    def delete(params) {
        InventoryItem.withTransaction { status ->
            def result = [:]

            def fail = { Map m ->
                status.setRollbackOnly()
                if(result.inventoryItemInstance && m.field)
                    result.inventoryItemInstance.errors.rejectValue(m.field, m.code)
                result.error = [ code: m.code, args: ["InventoryItem", params.id] ]
                return result
            }

            result.inventoryItemInstance = InventoryItem.get(params.id)

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

            if(result.inventoryItemInstance.inventoryMovements)
                return fail(code:"inventoryMovement.still.associated")

            result.inventoryItemInstance.removeReverseAlternateItems()

            try {
                result.inventoryItemInstance.delete(flush:true)
                return result //Success.
            }
            catch(org.springframework.dao.DataIntegrityViolationException e) {
                return fail(code:"default.delete.failure")
            }

        } //end withTransaction
    } // end delete()

    def edit(params) {
        def result = [:]
        def fail = { Map m ->
            result.error = [ code: m.code, args: ["InventoryItem", params.id] ]
            return result
        }

        result.inventoryItemInstance = InventoryItem.get(params.id)

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

        // Success.
        return result
    }

    def update(params) {
        InventoryItem.withTransaction { status ->
            def result = [:]

            def fail = { Map m ->
                status.setRollbackOnly()
                if(result.inventoryItemInstance && m.field)
                    result.inventoryItemInstance.errors.rejectValue(m.field, m.code)
                result.error = [ code: m.code, args: ["InventoryItem", params.id] ]
                return result
            }

            result.inventoryItemInstance = InventoryItem.get(params.id)

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

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

            def previousAlternateItems = new ArrayList(result.inventoryItemInstance.alternateItems)

            result.inventoryItemInstance.properties = params

            if(result.inventoryItemInstance.hasErrors() || !result.inventoryItemInstance.save())
                return fail(code:"default.update.failure")

            result.inventoryItemInstance.removeReverseAlternateItems(previousAlternateItems)
            result.inventoryItemInstance.addReverseAlternateItems()

            // Success.
            return result

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

    def create(params) {
        def result = [:]
        def fail = { Map m ->
            result.error = [ code: m.code, args: ["InventoryItem", params.id] ]
            return result
        }

        result.inventoryItemInstance = new InventoryItem()
        result.inventoryItemInstance.properties = params

        // success
        return result
    }

    def save(params) {
        InventoryItem.withTransaction { status ->
            def result = [:]

            def fail = { Map m ->
                status.setRollbackOnly()
                if(result.inventoryItemInstance && m.field)
                    result.inventoryItemInstance.errors.rejectValue(m.field, m.code)
                result.error = [ code: m.code, args: ["InventoryItem", params.id] ]
                return result
            }

            result.inventoryItemInstance = new InventoryItem(params)

            if(result.inventoryItemInstance.hasErrors() || !result.inventoryItemInstance.save())
                return fail(code:"default.create.failure")

            // success
            return result

        } //end withTransaction
    }

} // end class
