library(testit)

op = options(device = function(file = NULL, ...) {
  pdf(file, ...)
  dev.control('enable')  # important! otherwise plots get discarded
})

evaluate = evaluate::evaluate
classes = evaluate:::classes

# remove the blank plot
res = evaluate('layout(t(1:2))')
assert(
  'blank plots are removed',
  identical(classes(res), 'source')
)

assert(
  'plots generated by par(), palette() or layout() are removed',
{
  res = evaluate('par(mfrow = c(1, 2))\npie(islands)\nbarplot(islands)')
  identical(classes(res), rep(c('source', 'recordedplot'), c(3, 1)))
},
{
  res = evaluate('layout(t(1:2))\npie(islands)\nbarplot(islands)')
  identical(classes(res), rep(c('source', 'recordedplot'), c(3, 1)))
},
{
  res = evaluate('pie(islands)\nbarplot(islands)\npar(mfrow = c(1, 2))')
  res = merge_low_plot(res)
  identical(classes(res), rep(c('source', 'recordedplot'), length = 5))
},
{
  res = evaluate('pie(islands)\npar(cex.main=1.2)\nbarplot(islands)')
  res = merge_low_plot(res)
  identical(classes(res), c('source', 'recordedplot')[c(1, 2, 1, 1, 2)])
},
{
  res = evaluate('par(cex.main=1.2)\npalette(c("red","black"))\nbarplot(islands)')
  identical(classes(res), rep(c('source', 'recordedplot'), c(3, 1)))
}
)

res = evaluate('plot(1)\npoints(1.1, 1.1)')
assert(
  'merge low-level changes',
  identical(classes(res), rep(c('source', 'recordedplot'), 2)),
  identical(classes(merge_low_plot(res)), rep(c('source', 'recordedplot'), c(2, 1)))
)

res = evaluate('library(grid)
    grid.newpage()
    grid.rect(gp=gpar(fill="grey"))
    grid.rect(gp=gpar(fill="red"))')
assert(
  'captures grid graphics',
{
  identical(classes(res), c('source', 'recordedplot')[c(1, 1, 1, 2, 1, 2)])
},
{
  res = merge_low_plot(res)
  identical(classes(res), rep(c('source', 'recordedplot'), c(4, 1)))
}
)

options(op)

# rmarkdown sets dev.args = list(pdf = list(useDingbats = FALSE)) when dev = 'pdf'
if (!has_error({png(); dev.off()})) assert(
  'chunk_device() correctly opens the png device with dev.args',
  {
    chunk_device(opts_chunk$merge(list(
      dev = 'png', dev.args = list(pdf = list(useDingbats = FALSE))
    )))
    plot(1:10)
    dev.off()
    TRUE
  }
)
if (requireNamespace("ragg", quietly = TRUE) &&
    !has_error({ragg::agg_png(); dev.off()})) {
  assert(
    'chunk_device() correctly opens the ragg::agg_png device with dev.args',
    {
      chunk_device(opts_chunk$merge(list(
        dev = 'ragg_png', dev.args = list(pdf = list(useDingbats = FALSE))
      )))
      plot(1:10)
      dev.off()
      TRUE
    }
  )
  assert(
    'ragg_png_dev correctly handles bg dev.arg into background arg',
    {
      chunk_device(opts_chunk$merge(list(
        dev = 'ragg_png', dev.args = list(bg = "grey")
      )))
      plot(1:10)
      dev.off()
      TRUE
    }
  )
}
# should not error (find `pdf` correctly in grDevices, instead of the one
# defined below)
pdf = function() {}
do.call(pdf_null, list(7, 7))
dev.off()


gen_source = function(x) structure(x, class = 'source')
gen_plotrc = function(x) structure(factor(x), class = c('factor', 'recordedplot'))
res = list(
  gen_source(1), gen_plotrc('a'), gen_plotrc('b'), gen_source(2), gen_source(3),
  gen_plotrc('c'), gen_source(4), gen_plotrc('d')
)

assert(
  'fig_before_code() moves plots before code blocks',
  identical(fig_before_code(res), res[c(2, 3, 1, 4, 6, 5, 8, 7)])
)

# should not error when a plot label contains special characters and sanitize=TRUE
if (xfun::loadable('tikzDevice') &&
    (!is.na(Sys.getenv('CI', NA)) || Sys.getenv('USER') == 'yihui' || !xfun::is_macos())) {
  knit('knit-tikzDevice.Rnw', quiet = TRUE)
  unlink(c('*-tikzDictionary', 'figure', 'knit-tikzDevice.tex'), recursive = TRUE)
}

# https://github.com/yihui/knitr/issues/1166
knit(text = "\\Sexpr{include_graphics('myfigure.pdf', error = FALSE)}", quiet = TRUE)
