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

@Secured(['ROLE_AppAdmin', 'ROLE_Manager', 'ROLE_InventoryManager', 'ROLE_InventoryUser'])
class PictureDetailedController extends BaseController {

    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']

    def list = {
        prepareList()
        [ list: Picture.list(params), paginateCount: Picture.count() ]
    }

    void prepareList() {
        if (!params.max) {
            params.max = 10
        }
        if (!params.order) {
            params.order = "desc"
        }
        if (!params.sort) {
            params.sort = "id"
        }
    }

    def show = {
        // In the case of an actionSubmit button, rewrite action name from 'index'.
        if(params._action_Show)
            params.action='show'

        def picture = Picture.get( params.id )

        if(!picture) {
            flash.message = "Picture not found."
            redirect(action:list)
        }
        else { [ picture : picture ] }
    }

    def delete = {
        def picture = Picture.get(params.id)
        def inventoryItem = InventoryItem.get(picture?.inventoryItem?.id)

        if (inventoryItem && picture) {
            Picture.withTransaction { status ->
                inventoryItem.picture = null
                inventoryItem.save()
                picture.delete()
            }
            flash.message = "Picture ${params.id} deleted"
            redirect(controller: "inventoryItemDetailed", action: show, id: inventoryItem.id)

        }
        else {
            if(picture) {
                flash.message = "Removing orphan picture ${picture.id}."
                picture.delete(flush:true)
                redirect(action: list)
            }
            else {
                flash.message = "Picture not found"
                redirect(action: list)
            }
        }
    }

    def edit = {
        // In the case of an actionSubmit button, rewrite action name from 'index'.
        if(params._action_Edit)
            params.action='edit'

        def picture = Picture.get(params.id)
        if (!picture) {
            flash.message = "Picture not found"
            redirect(action: list)
        }
        else {
            [ picture : picture ]
        }
    }

    def update = {
        def picture = Picture.get(params.id)
        def inventoryItem = picture?.inventoryItem
        if (inventoryItem && picture) {

            if(params.version) {
                def version = params.version.toLong()
                if(picture.version > version) {
                    picture.errors.rejectValue("version", "picture.optimistic.locking.failure", "Another user has updated this Picture while you were editing.")
                    render(view:'edit',model:[picture:picture])
                    return
                }
            }

            picture.properties = params
            if (!picture.hasErrors()) {
                def imaging = new Imaging()
                def images = imaging.updateAll(picture)
                boolean result = false
                Picture.withTransaction{ status ->
                    result = picture.save()
                }
                if (result) {
                    flash.message = "Picture ${params.id} updated"
                    redirect(action: show, id: picture.id)
                }
                else {
                    render(view: 'edit', model: [ picture: picture ])
                }
            }
            else {
                render(view: 'edit', model: [ picture: picture ])
            }
        }
        else {
            flash.message = "Picture not updated, picture or inventory item not found."
            redirect(action: list)
        }
    }

    def create = {
        if(!params.inventoryItem?.id) {
            flash.message = "Please select an inventory item and then 'Add Picture'."
            redirect(controller: "inventoryItemDetailed", action: 'search')
            return
        }
        def picture = new Picture()
        picture.properties = params
        [ picture: picture ]
    }

    def save = {
        def inventoryItem = InventoryItem.get(params.inventoryItem.id)
        if (inventoryItem) {
            if(inventoryItem.picture) {
                flash.message = "Inventory item already has a picture, please delete the old picture first."
                redirect(controller: 'inventoryItemDetailed', action: 'show', id: inventoryItem.id)
                return
            }
            def picture = new Picture(params)
            def multiPartFile = request.getFile('file')
            def imaging = new Imaging()
            def images = null
            if (multiPartFile && !multiPartFile.isEmpty()) {
                if (multiPartFile.getSize() > Image.MAX_SIZE) {
                    picture.errors.rejectValue('file', 'picture.file.maxSize.exceeded',
                        [ 'file', 'Picture', Image.MAX_SIZE ] as Object[],
                        'Property [{0}] of class [{1}] image file is too big (maximum [{2}] bytes)')
                }
                else {
                    try {
                        images = imaging.createAll(inventoryItem, picture, multiPartFile.inputStream)
                    }
                    catch(Exception ex) {
                        log.error("picture save", ex)
                        picture.errors.rejectValue('file', 'picture.file.unrecognised',
                            [ 'file', 'Picture', multiPartFile.originalFilename ] as Object[],
                            'Property [{0}] of class [{1}] image file [{2}]: type not recognised')
                    }
                }
            }
            else {
                picture.errors.rejectValue('file', 'picture.file.missing',
                    ['file', 'Picture', ''] as Object[],
                    'Property [{0}] of class [{1}] no file specified')
            }
            if (images && !picture.hasErrors()) {
                boolean result = false
                Picture.withTransaction { status ->
                    images.each { image ->
                        picture.addToImages(image)
                    }
                    result = picture.save()
                    inventoryItem.picture = picture
                    inventoryItem.save()
                }
                if (result) {
                    flash.message = "Picture ${picture.id} created"
                    redirect(controller: 'inventoryItemDetailed', action: 'show', id: inventoryItem.id)
                }
                else {
                    render(view: 'create', model: [ picture: picture ])
                }
            }
            else {
                render(view: 'create', model: [ picture: picture ])
            }
        }
        else {
            flash.message = "Picture not created, inventory item not found."
            redirect(action: list)
        }
    }

    def view = {
        def picture = Picture.get(params.id)
        def size = params.size ? Integer.parseInt(params.size) : Image.Small
        def image = picture ? Image.findByPictureAndSize(picture, size) : null
        if (picture && image) {
            response.setContentType(image.contentType)
            response.setContentLength(image.data.size())
            response.setHeader('filename', image.filename())
            OutputStream out = response.outputStream
            out.write(image.data)
            out.close()
        }
        else {
            response.sendError(404)
        }
    }

}