##############################################################################
###                        MAIN PROGRAM                                    ###
##############################################################################
function(input, output, session) {

  # input data (with default)
  values <- reactiveValues(data_primary =  if ("startData" %in% names(.GlobalEnv)) startData else ExampleData.DeValues$BT998[7:11,],
                           data_secondary =  setNames(as.data.frame(matrix(NA_real_, nrow = 5, ncol = 2)), c("x", "y")),
                           data = NULL,
                           args = NULL)

  session$onSessionEnded(function() {
    stopApp()
  })

  # check and read in file (DATA SET 1)
  observeEvent(input$file1, {
    inFile<- input$file1

    if(is.null(inFile))
      return(NULL) # if no file was uploaded return NULL

    values$data_primary <- fread(file = inFile$datapath, data.table = FALSE) # inFile[1] contains filepath
    if (ncol(values$data_primary) > 2)
      values$data_primary <- values$data_primary[, 1:2]
  })

  # check and read in file (DATA SET 2)
  observeEvent(input$file2, {
    inFile<- input$file2

    if(is.null(inFile))
      return(NULL) # if no file was uploaded return NULL

    values$data_secondary <- fread(file = inFile$datapath, data.table = FALSE) # inFile[1] contains filepath
    if (ncol(values$data_secondary) > 2)
      values$data_secondary <- values$data_secondary[, 1:2]
  })

  ### GET DATA SETS
  observe({

    data <- list(values$data_primary, values$data_secondary)
    data <- lapply(data, function(x) { 
      x_tmp <- x[complete.cases(x), ]
      if (nrow(x_tmp) == 0) return(NULL)
      else return(x_tmp)
    })
    data <- data[!sapply(data, is.null)]
    data <- lapply(data, function(x) setNames(x, c("Dose", "Error")))

    values$data <- data
  })

  output$table_in_primary <- renderRHandsontable({
    rhandsontable(values$data_primary, 
                  height = 300, 
                  colHeaders = c("Dose", "Error"), 
                  rowHeaders = NULL)
  })

  observeEvent(input$table_in_primary, {
    res <- RLumShiny:::rhandsontable_workaround(input$table_in_primary)
    if (!is.null(res))
      values$data_primary <- res
  })

  output$table_in_secondary <- renderRHandsontable({
    rhandsontable(values$data_secondary, 
                  height = 300,
                  colHeaders = c("Dose", "Error"), 
                  rowHeaders = NULL)
  })

  observeEvent(input$table_in_secondary, {
    res <- RLumShiny:::rhandsontable_workaround(input$table_in_secondary)
    if (!is.null(res))
      values$data_secondary <- res
  })

  output$xlim<- renderUI({
    data <- values$data
    n <- max(sapply(data, nrow))

    sliderInput(inputId = "xlim", label = "Range x-axis",
                min = 0, max = n + 1,
                value = c(0, n) + 0.5)
  })

  output$ylim <- renderUI({
    data <- values$data[[1]]
    req(input$dose)
    if (input$dose[[1]] == 0) {
      ylim <- range(pretty(c(data[, 1] + data[, 2], data[, 1] - data[, 2])))
      sliderInput(inputId = "ylim", label = "Range y-axis",
                  min = pretty(ylim[1] * 0.5)[2],
                  max = ylim[2] * 1.5,
                  value = c(ylim[1], ylim[2]))
    } else {
      ## normalized values
      sliderInput(inputId = "ylim", label = "Range y-axis",
                  min = 0, max = 3,
                  value = c(0.75, 1.25),
                  step = 0.01)
    }
  })

  observeEvent(input$dose, {
    req(input$dose)
    updateTextInput(session, "ylab",
                    value = if (input$dose[[1]] == 0) "De [s]"
                            else "Normalised De")
  })

  observe({
    updateTextInput(session, inputId = "xlab",
                    value = if(input$preheat==TRUE){"Preheat Temperature [\u00B0C]"}else{"# Aliquot"})
  })

  observe({

    input$refresh

    outputOptions(x = output, name = "xlim", suspendWhenHidden = FALSE)
    outputOptions(x = output, name = "ylim", suspendWhenHidden = FALSE)

    # if custom datapoint style get char from separate input panel
    pch <- ifelse(input$pch == "custom", input$custompch, as.integer(input$pch))
    pch2 <- ifelse(input$pch2 == "custom", input$custompch2, as.integer(input$pch2))

    # if custom datapoint color get RGB code from separate input panel
    color <- ifelse(input$color == "custom", input$rgb, color<- input$color)

    # if custom datapoint color get RGB code from separate input panel
    if(length(values$data) > 1) {
      color2 <- ifelse(input$color2 == "custom", input$rgb2, input$color2)
    } else {
      color2 <- color
    }

    req(input$dose)
    if (length(values$data) == 1){
      given.dose<- input$dose
      legend<- input$legendname
    } else {
      given.dose<- c(input$dose, input$dose2)
      legend<- c(input$legendname, input$legendname2)
    }

    legend.pos <- input$legend.pos
    if (!input$showlegend) {
      legend <- NULL
      legend.pos <- c(-999, -999)
    }

    # save all arguments in a list
    values$args<- list(
      values = values$data,
      error.range = input$error,
      given.dose = as.numeric(given.dose),
      summary = as.character(input$stats),
      summary.pos = input$sumpos,
      boxplot = input$boxplot,
      legend = legend,
      legend.pos = legend.pos,
      main = input$main,
      mtext = input$mtext,
      col = c(color, color2),
      pch = c(pch, pch2),
      xlab = input$xlab,
      ylab = input$ylab,
      xlim = input$xlim,
      ylim = input$ylim,
      cex = input$cex)

    if (input$preheat) {

      n<- length(values$data[[1]][,1])
      ph<- c(input$ph1, input$ph2, input$ph3, input$ph4, input$ph5, input$ph6, input$ph7, input$ph8)
      ph<- ph[1:n]

    isolate({
      values$args<- c(values$args, "preheat" = NA)
      values$args$preheat<- ph

      values$args$pch<- rep(values$args$pch, n)
      values$args$col<- rep(values$args$col, n)
    })
    }
  })

  #### PLOT ####
  output$main_plot <- renderPlot({

    ## remove existing notifications
    removeNotification(id = "notification")

    validate(
      need(expr = input$ylim, message = 'Waiting for data... Please wait!'),
      need(expr = input$xlim, message = 'Waiting for data... Please wait!')
    )

    # plot DRT Results
    RLumShiny:::tryNotify(do.call(what = plot_DRTResults, args = values$args))
  })

  observe({
    # nested renderText({}) for code output on "R plot code" tab
    code.output <- callModule(RLumShiny:::printCode, "printCode",
                              n_inputs = 2,
                              list(name = "plot_DRTResults",
                                   arg1 = "data",
                                   args = values$args))

    output$plotCode<- renderText({
      code.output
    })##EndOf::renderText({})

    callModule(RLumShiny:::exportCodeHandler, "export", code = code.output)
    callModule(RLumShiny:::exportPlotHandler, "export", fun = "plot_DRTResults", args = values$args)
  })

  # renderTable() that prints the data to the second tab
  output$dataset<- DT::renderDT(
    options = list(pageLength = 10, autoWidth = FALSE),
    {
      data<- values$data
      colnames(data[[1]])<- c("De", "De error")
      data[[1]]
    })##EndOf::renterTable()

  # renderTable() that prints the data to the second tab
  output$dataset2<- DT::renderDT(
    options = list(pageLength = 10, autoWidth = FALSE),
    {
      data<- values$data
      if(length(data)>1) {
        colnames(data[[2]])<- c("De", "De error")
        data[[2]]
      }
    })##EndOf::renterTable()
}
