##' add subview to mainview for ggplot2 objects
##'
##' 
##' @title subview
##' @param mainview main view
##' @param subview a ggplot or grob object
##' @param x x position
##' @param y y position
##' @param width width of subview, [0,1]
##' @param height height of subview, [0,1]
##' @return ggplot object
##' @importFrom ggplot2 annotation_custom
##' @importFrom ggplot2 ggplotGrob
##' @export
##' @author Guangchuang Yu
subview <- function(mainview, subview, x, y, width=.1, height=.1) {
    mapping <- mainview$mapping %>% as.character
    aes_x <- mapping["x"]
    aes_y <- mapping["y"]
    
    xrng <- mainview$data[, aes_x] %>% range 
    yrng <- mainview$data[, aes_y] %>% range

    for (i in seq_along(mainview$layers)) {
        layer <- mainview$layers[[i]]
        dd <- layer$data
        if (is(dd, "data.frame")) {
            mapping <- as.character(layer$mapping)
            mn <- names(mapping)
            if ('x' %in% mn) {
                aes_x <- mapping["x"]
                xrng <- c(xrng, layer$data[, aes_x])
            }
            if ('xmin' %in% mn) {
                aes_x <- mapping["xmin"]
                xrng <- c(xrng, layer$data[, aes_x])
            }
            if ('xmax' %in% mn) {
                aes_x <- mapping["xmax"]
                xrng <- c(xrng, layer$data[, aes_x])
            }
            if ('y' %in% mn) {
                aes_y <- mapping["y"]
                yrng <- c(yrng, layer$data[, aes_y])
            }
            if ('ymin' %in% mn) {
                aes_y <- mapping["ymin"]
                yrng <- c(yrng, layer$data[, aes_y])
            }
            if ('ymax' %in% mn) {
                aes_y <- mapping["ymax"]
                yrng <- c(yrng, layer$data[, aes_y])
            }
            xrng <- range(xrng)
            yrng <- range(yrng)
        }
    }

    xrng <- diff(xrng)
    yrng <- diff(yrng)
    
    if (!any(class(subview) %in% c("ggplot", "grob", "character"))) {
        stop("subview should be a ggplot or grob object, or an image file...")
    }
    
    if (is(subview, "ggplot")) {
        sv <- ggplotGrob(subview)
    } else if (is(subview, "grob")) {
        sv <- subview
    } else if (file.exists(subview)) {
        readImage <- get_fun_from_pkg("EBImage", "readImage")
        sv <- rasterGrob(readImage(subview))
    } else {
        stop("subview should be a ggplot or grob object, or an image file...")
    }

    width <- width/2
    height <- height/2
    
    mainview + annotation_custom(
        sv,
        xmin = x - width*xrng,
        xmax = x + width*xrng,
        ymin = y - height*yrng,
        ymax = y + height*yrng)
}