core_intro_module_ui <- function(id) {
  ns <- shiny::NS(id)
  tagList(
    tags$div(
      style="display: flex; flex-direction: column; align-items: center; padding: 20px;",
      actionButton(ns("intro"), "Start a guided tour", icon = icon("person-hiking", lib = "font-awesome"), width = "360px", style = "font-size: 1.5rem; margin-bottom: 20px;"),
      actionButton(ns("existing_intro"), "See what has changed", icon = icon("person-hiking", lib = "font-awesome"), width = "360px", style = "font-size: 1.5rem;")
    )
  )
}

core_intro_module_server <- function(id, common, parent_session) {
  moduleServer(id, function(input, output, session) {

  #Steps in the introduction - the element to tag, the message to display, position of the tooltip, any javascript needed to move between tabs / click buttons
  steps <- data.frame(c(NA, "Welcome to MetaInsight! This tour will show you various features of the application to help get you started", NA, NA),
                      c("aside[class=\"sidebar\"]", "This panel shows all of the possible modules in the app", "bottom", NA),
                      c("a[data-value=\"How to use\"]", "Detailed instructions can be found in the How To Use tab", "bottom","$('a[data-value=\"How To Use\"]').trigger('click');"),
                      c("a[data-value=\"setup\"]", "Click on the tabs to move between sections", "bottom", "$('a[data-value=\"setup\"]').trigger('click');"),
                      c("#setupSel", "Select a module to load the options", "bottom", "$('input[value=\"setup_load\"]').trigger('click');"),
                      c("#setup_loadHelp", "Click on the question mark to view instructions for the module - Note that these are mostly not yet written", "bottom", "$('a[data-value=\"Module Guidance\"]').trigger('click');"),
                      c("#setup_input_panel", "This panel shows possible options for the module.", "bottom", NA),
                      c("#global_options", "These options affect the whole app - choose the type of model and file format for plot downloads.", "bottom", NA),
                      c("#setup_load-run", "Click the button or press the Enter key on your keyboard to run the module", "bottom", NA),
                      c("#setup_exclude-collapse", "Once you have configured the analysis you can view a summary forest plot of the studies and click to exclude them from the sensitivity analysis", "bottom", NA),
                      c("a[data-value=\"Results\"]", "Plots and tables generated by the selected module are displayed in the Results tab", "bottom", "$('a[data-value=\"Results\"]').trigger('click');
                                                                                                                                                      $(Shiny.setInputValue('processing_intro', 'true'));"),
                      c("#processing_icon", "Some computation occurs in the background and this icon appears when it is processing", "bottom", NA),
                      c("div[id=\"messageLog\"]", "Messages will appear in the log window", "bottom", "$(Shiny.setInputValue('processing_intro', null));"),
                      c("a[data-value=\"export\"]", "You can download code to reproduce your analysis in the Session Code module", "bottom","$('a[data-value=\"export\"]').trigger('click');
                                                                                                                                          $('input[value=\"export_markdown\"]').trigger('click');"),
                      c("a[data-value=\"Save\"]", "You can download a file which saves the state of the app", "left", "$('a[data-value=\"Save\"]').trigger('click');"),
                      c("a[data-value=\"setup\"]", "Next time you visit...", "bottom", "$('a[data-value=\"setup\"]').trigger('click');
                                                                                        $('input[value=\"setup_reload\"]').trigger('click');"),
                      c("#reload_inputs", "you can upload the file in the setup section to restore the app", "bottom", NA),
                      c(NA, "You are ready to go!", NA, "$('input[value=\"setup_load\"]').trigger('click');
                                                         $('a[data-value=\"intro\"]').trigger('click');
                                                         $('a[data-value=\"About\"]').trigger('click');")

  )
  #transpose and add columns names
  steps <- as.data.frame(t(steps))
  colnames(steps) <- c("element", "intro", "position", "javascript")

  #extract the javascript into one string
  intro_js <- ""
  for (r in 1:nrow(steps)){
    if (!is.na(steps$javascript[r])){
      intro_js <- paste(intro_js, paste0("if (this._currentStep == ",r-1,") {",steps$javascript[r],"}"))
    }
  }
  intro_js <- gsub("[\r\n]", "", intro_js)

  #launch intro if the button is clicked
  observeEvent(input$intro,{
    rintrojs::introjs(session, options = list(steps = steps, "showBullets" = "true", "showProgress" = "true",
                                              "showStepNumbers" = "false", "nextLabel" = "Next", "prevLabel" = "Prev", "skipLabel" = "Exit"),
                      events = list(onbeforechange = I(intro_js),
                                    onexit = I("$(Shiny.setInputValue('processing_intro', null));"))
               )
    })


  existing_steps <- data.frame(
    c(NA, "Welcome to MetaInsight! This tour will explain what has changed from earlier versions. Nothing has been removed but the interface has been redesigned and analyses are now reproducible.", NA, NA),
    c("a[data-value=\"setup\"]", "The tabs at the top move between sections of the app which combines the previous 'Load data' tab and all of the sub-tabs found in the 'Data analysis' tab.", "bottom", "$('a[data-value=\"setup\"]').trigger('click');"),
    c("#setupSel", "Inside each section this panel shows the available 'modules' which correspond to the second layer of tabs in the previous 'Data analysis' tab.", "bottom", "$('input[value=\"setup_load\"]').trigger('click');"),
    c("#setup_input_panel", "All the possible options for the module are shown in this panel, including downloading any outputs.", "bottom", NA),
    c("#setup_load-run", "A major change is that each module must be explicitly run by either clicking the button or pressing the Enter key on your keyboard.", "bottom", NA),
    c("#setup_loadHelp", "Each module has a guidance page explaining how to use it and some of the technical background - Note that these are mostly not yet written", "bottom", "$('a[data-value=\"Module Guidance\"]').trigger('click');"),
    c("#setupSel", "After uploading data, you now need to also configure the analysis.", "bottom", "$('input[value=\"setup_configure\"]').trigger('click');"),
    c("#global_options", "Some options that were previously in the sidebar are now in this panel. You can set the file format of plot downloads for all modules in one place", "bottom", NA),
    c("#setup_exclude-collapse", "Once you have configured the analysis you can view a summary forest plot of the studies and click to exclude them from the sensitivity analysis", "bottom", NA),
    c("a[data-value=\"Results\"]", "Plots and tables generated by the selected module are displayed in the Results tab", "bottom", "$('a[data-value=\"Results\"]').trigger('click');
                                                                                                                                    $(Shiny.setInputValue('processing_intro', 'true'));"),
    c("#processing_icon", "Some computation occurs in the background and this icon appears when it is processing. This includes Bayesian models which now update automatically when studies are excluded.", "bottom", NA),
    c("div[id=\"messageLog\"]", "Messages will appear in the log window to update you on background jobs and any errors", "bottom", "$(Shiny.setInputValue('processing_intro', null));"),
    c("a[data-value=\"export\"]", "At any point you can download code to reproduce your analysis in the Session Code module.
                                You can rerun this in R on your own computer and produce the same results", "bottom","$('a[data-value=\"export\"]').trigger('click');
                                                                                                                      $('input[value=\"export_markdown\"]').trigger('click');"),

    c("a[data-value=\"Save\"]", "You can also download a file which saves the state of the app and then ...", "left", "$('a[data-value=\"Save\"]').trigger('click');"),
    c("a[data-value=\"setup\"]", "... next time you visit ...", "bottom", "$('a[data-value=\"setup\"]').trigger('click');
                                                                      $('input[value=\"setup_reload\"]').trigger('click');"),
    c("#reload_inputs", "you can upload the file in the setup section to restore the app", "bottom", NA),
    c(NA, "You are ready to go! Please send any feedback to apps@crsu.org.uk", NA, "$('input[value=\"setup_load\"]').trigger('click');
                                                                                    $('a[data-value=\"intro\"]').trigger('click');
                                                                                    $('a[data-value=\"About\"]').trigger('click');")
  )

  #transpose and add columns names
  existing_steps <- as.data.frame(t(existing_steps))
  colnames(existing_steps) <- c("element", "intro", "position", "javascript")

  #extract the javascript into one string
  existing_intro_js <- ""
  for (r in 1:nrow(existing_steps)){
    if (!is.na(existing_steps$javascript[r])){
      existing_intro_js <- paste(existing_intro_js, paste0("if (this._currentStep == ",r-1,") {",existing_steps$javascript[r],"}"))
    }
  }
  existing_intro_js <- gsub("[\r\n]", "", existing_intro_js)

  #launch intro if the button is clicked
  observeEvent(input$existing_intro,{
    rintrojs::introjs(session, options = list(steps = existing_steps, "showBullets" = "true", "showProgress" = "true",
                                              "showStepNumbers" = "false", "nextLabel" = "Next", "prevLabel" = "Prev", "skipLabel" = "Exit"),
                      events = list(onbeforechange = I(existing_intro_js),
                                    onexit = I("$(Shiny.setInputValue('processing_intro', null));"))
    )
  })

  })
}

