library(shiny)
library(Seurat)
library(shinyFiles)
library(ggplot2)
library(ggpubr)

# Define UI for application
ui <- fluidPage(

    # Application title
    titlePanel("scMonitor"),

    sidebarLayout(
        sidebarPanel(
          shinyFilesButton("file", label="Select File", title="Select a Seurat Object", multiple=F),
          uiOutput('groupby'),
          uiOutput('facetby'),
          textInput('features', label = "Genes"),
          textInput('mods', label = "Signatures"),
          actionButton("goButton", "Query"),
          sliderInput("height", "Altura", min=1000, max=20000, step=1000, value=6000),
          h3("Add Signature"),
          textInput('mod_name', label = "Name"),
          textInput('mod_feat', label = "Genes"),
          actionButton("modButton", "Add Signature")
        ),

        mainPanel(
           plotOutput("umapPlot"),
           uiOutput("featPlotUI")
        )
    )
)

# Define server logic
server <- function(input, output) {
  
  ## Defining reactive values
  dades<-reactiveValues()
  dades$seu<-NULL
  dades$mods<-NULL
  
  ## Conecting with file location and entering Seurat object
  volumes <- c(Home = fs::path_home(), "R Installation" = R.home(), getVolumes()())
  shinyFileChoose(input, 'file', roots=volumes)
  
  observe({
    if (!is.integer(input$file)){
      dades$seu<-readRDS(parseFilePaths(volumes, input$file)$datapath)
    }
  })
  
  ## Rendering UI depending on seu meta.data
  output$groupby<-renderUI({
    if (!is.null(dades$seu)){
      selectInput("groupby", "GroupBy", c("Default", colnames(dades$seu@meta.data)))
    }
  })
  
  output$facetby<-renderUI({
    if (!is.null(dades$seu)){
      selectInput("facetby", "FacetBy", c("None", colnames(dades$seu@meta.data)))
    }
  })
  
  ## Render DimPlot
  output$umapPlot <- renderPlot({
    observeEvent(dades$seu, {})
    if (!is.null(dades$seu)){
 
    plot<-DimPlot(dades$seu, 
                  group.by = if(input$groupby != "Default"){input$groupby}else{NULL},
                  split.by=if(input$facetby != "None"){input$facetby}else{NULL})+
      theme(aspect.ratio=1)
    plot
    }
  })
  
  ## Signature - Module Definition
  observeEvent(input$modButton, {
    if (input$modButton > 0){
      mod_list<-strsplit(input$mod_feat, " ")[[1]]
      mod_list<-mod_list[mod_list %in% rownames(dades$seu)]
      dades$seu<-AddModuleScore(dades$seu,list(mod_list),
                                name=input$mod_name)
    }
  })
  
  ## FeaturePlot construction
  query<-eventReactive(input$goButton,{
    dades$fet_query<-strsplit(input$features, " ")[[1]]
  })
  
  output$featPlotUI<- renderUI({
    observeEvent(dades$fet_query, {})
    if (!is.null(dades$seu)){
      plotOutput("featPlot", 
                 height = paste0(input$height/10,"px"))
    }
  })

  ## ModulePlot/SigPlot construction
  query_mod<-eventReactive(input$goButton,{
    if (length(strsplit(input$mods, " ")[[1]]) > 0){
      dades$mods<-paste(strsplit(input$mods, " ")[[1]], "1", sep="")
    }else{
      dades$mods<-NULL
    }
  })
  
  output$modPlotUI<- renderUI({
    observeEvent(dades$mod_name, {})
    if (!is.null(dades$mod_name)){
      plotOutput("modPlot",
                 height = paste0(input$height/10,"px"))
    }
  })
  
  ## Feature/Mod plot rendering
  output$featPlot<-renderPlot({
    observeEvent(input$goButton, {})
    if (!is.null(dades$seu)){
      query()
      plot<-list()
      print(dades$fet_query)
      if (length(dades$fet_query) > 0){
        plot[["Genes"]]<-FeaturePlot(dades$seu,
                    split.by=if(input$facetby != "None"){input$facetby}else{NULL},
                    features = dades$fet_query)&theme(aspect.ratio = 1)
      }
      query_mod()
      print(dades$mods)
      if (length(dades$mods) > 0){
        plot[["Mods"]]<-FeaturePlot(dades$seu,
                    split.by=if(input$facetby != "None"){input$facetby}else{NULL},
                    features = dades$mods)&theme(aspect.ratio = 1)&scale_color_viridis_c()
      }
      do.call(ggarrange, c(plot, ncol=1))
    }
  })

  
}

# Run the application 
shinyApp(ui = ui, server = server)
