#' @title Plot an inset
#' @description This function is used to add an inset map to the current map.
#' @param x an sf object, or "worldmap" to use with \link{mf_worldmap}.
#' @param pos position, one of "bottomleft", "left", "topleft", "top", "bottom",
#' "bottomright", "right", "topright"
#' @param cex share of the map width occupied by the inset
#' @param fig coordinates of the inset region (in NDC, see in ?par())
#' @export
#' @details
#' If x is used (with pos and cex), the width/height ratio of the inset will
#' match the width/height ratio of x bounding box.\cr
#' If fig is used, coordinates (xmin, xmax, ymin, ymax) are expressed as
#' fractions of the mapping space (i.e. excluding margins).\cr
#' If map layers have to be plotted after the inset (i.e after mf_inset_off()),
#' please use add = TRUE.\cr
#' It is not possible to plot an inset within an inset.\cr
#' It is possible to plot anything (base plots) within the inset, not only map
#' layers.
#' @return No return value, an inset is initiated or closed.
#' @examples
#' mtq <- mf_get_mtq()
#' mf_map(mtq)
#' mf_inset_on(x = mtq[1, ], cex = .2)
#' mf_map(mtq[1, ])
#' mf_inset_off()
#'
#' mf_map(mtq)
#' mf_inset_on(x = "worldmap", pos = "bottomleft")
#' mf_worldmap(x = mtq)
#' mf_inset_off()
#'
#' mf_map(mtq)
#' mf_inset_on(fig = c(0, 0.25, 0, 0.25))
#' mf_map(x = mtq)
#' mf_inset_off()
mf_inset_on <- function(x, pos = "topright", cex = .2, fig) {
  test_cur_plot()

  if (.gmapsf$inset) {
    stop(
      paste0(
        "You have already started an inset. ",
        "Use `mf_inset_off()` to close the current inset."
      ),
      call. = FALSE
    )
  }
  .gmapsf$inset <- TRUE
  pusr <- par("usr")
  .gmapsf$par <- par(no.readonly = TRUE)
  if (!missing(x)) {
    if (is.character(x)) {
      if (x == "worldmap") {
        h <- 1
        w <- 1
      }
    } else {
      bb <- st_bbox(x)
      w <- bb[3] - bb[1]
      h <- bb[4] - bb[2]
    }
    ratio <- h / w
    wdest <- (pusr[2] - pusr[1]) * cex
    hdest <- wdest * ratio
    inset_xy <- posinset(pos = pos, pusr = pusr, wdest = wdest, hdest = hdest)
    tgx <- c(
      grconvertX(inset_xy[1:2], from = "user", to = "ndc"),
      grconvertY(inset_xy[3:4], from = "user", to = "ndc")
    )
  }

  if (!missing(fig)) {
    ffig <- c(
      grconvertX(pusr[1:2], from = "user", to = "ndc"),
      grconvertY(pusr[3:4], from = "user", to = "ndc")
    )
    tgtx <- fig[1:2]
    tgty <- fig[3:4]

    ffig2 <- c(tgtx * (ffig[2] - ffig[1]), tgty * (ffig[4] - ffig[3]))
    tgx <- c(ffig[1] + ffig2[1:2], ffig[3] + ffig2[3:4])
  }

  theme <- mf_theme()
  .gmapsf$oth <- theme
  .gmapsf$mfg <- par("mfg")

  if (max(tgx) > 1 || min(tgx) < 0) {
    tgx[tgx > 1] <- 1
    tgx[tgx < 0] <- 0
  }
  par(bg = NA)
  par(
    fig = round(tgx, 3),
    mar = c(0, 0, 0, 0),
    new = TRUE
  )
  theme$mar <- c(0, 0, 0, 0)
  theme$background <- NA
  mf_theme(theme)
}


#' @name mf_inset_on
#' @export
mf_inset_off <- function() {
  .gmapsf$inset <- FALSE
  pusr <- .gmapsf$par$usr
  par(.gmapsf$par)
  par(new = TRUE, mar = .gmapsf$oth$mar)
  plot.new()
  plot.window(
    xlim = pusr[1:2], ylim = pusr[3:4],
    xaxs = "i", yaxs = "i", asp = TRUE
  )
  mf_theme(.gmapsf$oth)
  par(mar = .gmapsf$par$mar, mfg = .gmapsf$mfg)
  points(1, 1, col = NA)
}
