#' @title Add an inset within a map
#' 
#' @details
#' If add = TRUE, the location is calculated through the extent of current map.
#' If add = FALSE, the location is calcultaed through the extent of y.
#' 
#' The function is based on the facility to rescale and translate sf object.
#' 
#' @param x should be a sf object or at least readable by sf::st_geometry.
#' @param y should be a sf object or at least readable by sf::st_bbox.
#' @param ratio numeric, how big should be the inset relative to the whole map
#' or to y. See details.
#' @param add loical, should the inset be added to an existing plot.
#' @param ...  some parameters that will be used by sf::plot
#'
#' @return sf geometry transformed to be placed in the good loaction in the map.
#'
#' @export
#'
#' @encoding UTF-8
#' 
#' @examples
#' 
#' library(sf)
#' so.ii::map_so_ii()
#' inset = add_inset(
#'   so.ii::so_ii_inset[c("region", "so-ii"), ],
#'   so.ii::so_ii_limit,
#'   col = c("gray", "red"), border = c(NA, "red"), lwd = 1:2
#' )

add_inset = function(x, y, ratio = 1/5, add = TRUE, ...) {
    ext_y = if (add == TRUE) {
        sf::st_bbox(stats::setNames(graphics::par("usr"), c("xmin", "xmax", "ymin", "ymax")))
    } else {
        sf::st_bbox(y)
    }

    x = sf::st_geometry(x)
    ext_x = sf::st_bbox(x)
    ratio = ratio * min(c(
        diff(ext_y[c("xmin", "xmax")]) / diff(ext_x[c("xmin", "xmax")]),
        diff(ext_y[c("ymin", "ymax")]) / diff(ext_x[c("ymin", "ymax")])
    ))
    centroid = suppressWarnings(sf::st_centroid(x))
    x = (x - centroid) * ratio
    ext_x = sf::st_bbox(x)
    ratio_real = stats::setNames(c(
        diff(ext_x[c("xmin", "xmax")]) / diff(ext_y[c("xmin", "xmax")]),
        diff(ext_x[c("ymin", "ymax")]) / diff(ext_y[c("ymin", "ymax")])
    ), c("x", "y"))

    pos = c(
        ext_y[["xmin"]] + diff(ext_y[c("xmin", "xmax")]) * (ratio_real["x"] / 2 + 0.02),
        ext_y[["ymax"]] - diff(ext_y[c("ymin", "ymax")]) * (ratio_real["y"] / 2 + 0.02)
    )
    pos = sf::st_sfc(sf::st_point(pos))
    sf::st_crs(pos) = sf::st_crs(y)
    x =  x + pos + (centroid - centroid[1]) * ratio
    sf::st_crs(x) = sf::st_crs(y)

    if (add == TRUE) plot(x, ..., add = TRUE)
    return(invisible(x))
}


