/**
 * Provides a service class for the PurchaseOrder and PurchaseOrderNumber domain classes.
 */
class PurchaseOrderService {

    boolean transactional = false

    def savePurchaseOrderNumberRange(prefix, startOfRange, endOfRange, suffix="") {
        PurchaseOrderNumber.withTransaction { status ->
            def result = [:]

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

            // Sanity checks.
            if(startOfRange < 0)
                return fail(code:"default.create.failure")
            if(endOfRange < 0)
                return fail(code:"default.create.failure")
            // Auto swap range.
            if(endOfRange < startOfRange)
                (startOfRange, endOfRange) = [endOfRange, startOfRange]

            def r
            def p = [:]
            for(i in startOfRange..endOfRange) {
                p.value= "${prefix}${i}${suffix}"
                r = savePurchaseOrderNumber(p)
                if(r.error)
                    return fail(code: r.code)
                    
            }

            // Success.
            return result
        }
    }

    PurchaseOrderNumber findNextUnusedPurchaseOrderNumber() {
        def empty = PurchaseOrderNumber.list().find{it.purchaseOrder==null}
        return empty
    }

    PurchaseOrder getOrCreatePurchaseOrder(params) {
        def id = params.purchaseOrderNumber.id
        if (params.purchaseOrderNumber.id instanceof Long) {
            id = params.purchaseOrderNumber.id
        } else {
            id = params.purchaseOrderNumber.id.toString().toLong()
        }
        def pon = PurchaseOrderNumber.get(id)
        def po = pon?.purchaseOrder
        if (!po) {
            po = createPurchaseOrder(pon,params)
        }
        return po
    }

    PurchaseOrder createPurchaseOrder(pon,params) {
        def supplier = Supplier.get(params.supplier.id)
        def po = new PurchaseOrder(supplier:supplier)
        pon.purchaseOrder = po
        po.purchaseOrderNumber = pon
        pon.save(failOnError:true) // should cascade to save the PO as well. I wonder why it doesn't.
        po.save(failOnError:true)
        return po
    }

    List<PurchaseOrder> findDraftPurchaseOrderNumbers() {
        def drafts = PurchaseOrder.list().findAll{it.ordered == null}.collect{it.purchaseOrderNumber}
        return drafts
    }

    def savePurchaseOrderNumber(params) {
        PurchaseOrderNumber.withTransaction { status ->
            def result = [:]

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

            result.purchaseOrderNumber = new PurchaseOrderNumber(params)

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

            // Success.
            return result
        }
    }

}
