##' layer of hilight clade with rectangle
##'
##' @title geom_hilight
##' @param node selected node to hilight (required)
##' @param fill color fill (default = steelblue)
##' @param alpha alpha transparency, (default = 0.5)
##' @param extend extend xmax of the rectangle (default = 0)
## @param extendto extend xmax to extendto (default = NULL), only works for rectangular and circular/fan layouts
##' @param ... additional parameters
##' @return ggplot2
##' @export
##' @importFrom ggplot2 aes_
##' @importFrom ggplot2 GeomRect
##' @author Guangchuang Yu
geom_hilight <- function(node, fill="steelblue", alpha=.5, extend=0, ...) {
    structure(list(node = node,
                   fill = fill,
                   alpha = alpha,
                   extend = extend,
                   ## extendto = extendto,
                   ...),
              class = 'hilight')
}



geom_hilight_rectangular <- function(node, mapping = NULL, fill="steelblue",
                                     alpha=.5, extend=0, extendto=NULL) {
  data = NULL
  stat = "hilight"
  position = "identity"
  show.legend = NA
  na.rm = TRUE
  inherit.aes = FALSE
  check.aes = FALSE

  default_aes <- aes_(x=~x, y=~y, node=~node, parent=~parent, branch = ~branch)

  if (is.null(mapping)) {
      mapping <- default_aes
  } else {
      mapping <- modifyList(default_aes, mapping)
  }


  layer(
    stat=StatHilight,
    data = data,
    mapping = mapping,
    geom = GeomRect,
    position = position,
    show.legend=show.legend,
    inherit.aes = inherit.aes,
    check.aes = check.aes,
    params = list(node=node,
                  fill=fill,
                  alpha=alpha,
                  extend=extend,
                  extendto=extendto,
                  na.rm = na.rm)
  )
}

##' stat_hilight
##'
##' @title stat_hilight
##' @param mapping aes mapping
##' @param data data
##' @param geom geometric object
##' @param position position
##' @param node node number
##' @param show.legend show legend
##' @param inherit.aes logical
##' @param fill fill color
##' @param alpha transparency
##' @param extend extend xmax of the rectangle
##' @param extendto extend xmax to extendto
##' @param ... additional parameter
##' @return layer
##' @importFrom ggplot2 layer
##' @export
stat_hilight <- function(mapping=NULL, data=NULL, geom="rect",
                         position="identity",  node,
                         show.legend=NA, inherit.aes=FALSE,
                         fill, alpha, extend=0, extendto=NULL,
                         ...) {

  default_aes <- aes_(x=~x, y=~y, node=~node, parent=~parent, branch=~branch) #, branch.length=~branch.length)

  if (is.null(mapping)) {
    mapping <- default_aes
  } else {
    mapping <- modifyList(default_aes, mapping)
  }

  layer(
    stat=StatHilight,
    data = data,
    mapping = mapping,
    geom = geom,
    position = position,
    show.legend=show.legend,
    inherit.aes = inherit.aes,
    params = list(node=node,
                  fill=fill,
                  alpha=alpha,
                  extend=extend,
                  extendto=extendto,
                  ...)
  )
}

##' StatHilight
##' @rdname ggtree-ggproto
##' @format NULL
##' @usage NULL
##' @importFrom ggplot2 Stat
##' @export
StatHilight <- ggproto("StatHilight", Stat,
                       compute_group = function(self, data, scales, params, node, extend, extendto) {
                           df <- get_clade_position_(data, node)
                           df$xmax <- df$xmax + extend
                           if (!is.null(extendto) && !is.na(extendto)) {
                               if (extendto < df$xmax) {
                                   warning("extendto is too small, keep the original xmax value...")
                               } else {
                                   df$xmax <- extendto
                               }
                           }
                           return(df)
                       },
                       required_aes = c("x", "y") #, "branch.length")
                       )


##' get position of clade (xmin, xmax, ymin, ymax)
##'
##'
##' @title get_clade_position
##' @param treeview tree view
##' @param node selected node
##' @return data.frame
##' @export
##' @author Guangchuang Yu
get_clade_position <- function(treeview, node) {
  get_clade_position_(treeview$data, node)
}

get_clade_position_ <- function(data, node) {
    sp <- tryCatch(offspring.tbl_tree(data, node)$node, error=function(e) NULL)
    i <- match(node, data$node)
    if (is.null(sp)) {
        ## tip
        sp.df <- data[i,]
    } else {
        sp <- c(sp, node)
        sp.df <- data[match(sp, data$node),]
    }
    
    x <- sp.df$x
    y <- sp.df$y
    
    if ("branch.length" %in% colnames(data)) {
        xmin <- min(x, na.rm=TRUE) - data[["branch.length"]][i]/2
    } else {
        xmin <- min(sp.df$branch, na.rm=TRUE)
    }
    data.frame(xmin=xmin,
               xmax=max(x, na.rm=TRUE),
               ymin=min(y, na.rm=TRUE) - 0.5,
               ymax=max(y, na.rm=TRUE) + 0.5)
}