library(shiny)
library(shinyjs)
library(shinyWidgets)
library(waiter)
library(dplyr)
library(readr)
library(tools)
library(clustifyr)
library(clustifyrdatahub)
library(rsconnect)
library(ExperimentHub)
library(Seurat)
library(shinydashboard)
library(bsplus)
library(dashboardthemes)
library(tidyverse)
library(data.table)
library(R.utils)
library(DT)
library(GEOquery)
library(pheatmap)
library(googlesheets4)
library(openxlsx)
library(httr)

options(shiny.maxRequestSize = 1500 * 1024^2)
options(repos = BiocManager::repositories())
options(datatable.fread.datatable = FALSE)
options(shiny.reactlog = TRUE)
options(
  DT.options = list(
    dom = "tp",
    paging = TRUE,
    pageLength = 6,
    scrollX = TRUE,
    server = TRUE
  )
)

is_local <- Sys.getenv('SHINY_PORT') == ""

# google sheet
gs4_auth(cache = "sheet", email = TRUE, use_oob = TRUE)
sheetid <- "https://docs.google.com/spreadsheets/d/107qXuwo568wmPikaNDIe1supkGOYakwnRhiaTaL7U8c"

# setup experimenthub
eh <- ExperimentHub()
refs <- query(eh, "clustifyrdatahub")
refs_meta <- mcols(refs) %>% as.data.frame()
ref_dict <- refs$ah_id %>% setNames(refs$title)

# get clicked column
js <- c(
  "table.on('click', 'td', function(){",
  "  var cell = table.cell(this);",
  "  var colindex = cell.index().column;",
  "  var colname = table.column(colindex).header().innerText;",
  "  Shiny.setInputValue('column_clicked', colname);",
  "});"
)

# get active tab
js2 <- '
$(document).ready(function(){
  $("a[data-toggle=tab]").on("show.bs.tab", function(e){
    Shiny.setInputValue("activeTab", $(this).attr("data-value"));
  });
});
'

# GEO functions
make_button <- function(tbl){
  function(i){
    sprintf(
      paste0('<button id="button_%s_%d', '_', format(Sys.time(), "%H_%M_%S"), '" type="button" onclick="%s">Preview</button>'),
      tbl, i, "Shiny.setInputValue('button', this.id);")
  }
}

get_tar <- function(link) {
  paste0(
    str_remove(link, "/GSE[0-9]+_RAW.tar"),
    "/filelist.txt"
  )
}

get_file_size <- function(url) {
  response <- httr::HEAD(url)
  size <- tryCatch(httr::headers(response)[["Content-Length"]] %>% as.numeric(),
                   error = "error_get")
  if (is.null(size)) {
    return("error_get")
  }
  utils:::format.object_size(size, "auto")
}

list_geo <- function(id) {
  message("fetching info for all files available...")
  # look for files
  out <- tryCatch(suppressMessages(GEOquery::getGEOSuppFiles(id,
                                                             makeDirectory = FALSE,
                                                             fetch_files = FALSE))$fname,
                  error = function(e) {
                    "error_get"
                  })
  # make links
  if (is.null(out)) {
    return("error_get")
  } 
  
  if (out == "error_get") {
    return("error_get")
  }

  out <- data.frame(file = out) %>%
    mutate(link = str_c("https://ftp.ncbi.nlm.nih.gov/geo/series/GSE",
                        str_extract(file, "[0-9]{3}"),
                        "nnn/",
                        id,
                        "/suppl/",
                        file))
  out
}

prep_email <- function(id) {
  out <- tryCatch(
    suppressMessages(GEOquery::getGEO(
      GEO = id,
      filename = NULL,
      GSElimits = NULL, GSEMatrix = FALSE,
      AnnotGPL = FALSE, getGPL = FALSE,
      parseCharacteristics = FALSE
    )),
    error = function(e) {
      "error_get"
    })
  if (class(out) != "GSE") {
    return(out)
  } else {
    name <- paste0("Dr ", out@header$contact_name %>% str_remove(".+,"))
    if (id == "GSE113049") {
      email <- "placeholder@forexample.com"
    } else {
      email <- out@header$contact_email
    }

    link <- paste0("mailto:",
                   email,
                   "?subject=additional info request for ",
                   id,
                   "&body=Dear ",
                   name,
                   ",%0D%0A%0D%0ACan you please provide additional metadata information for the single cell dataset deposited on GEO, ",
                   id,
                   ".",
                   "%0D%0A%0D%0AThank you so much")
    return(link)
  }
}

preview_link <- function(link, n_row = 5, n_col = 50, verbose = TRUE) {
  # make sure link works
  message(link)
  if (!str_starts(str_to_lower(link), "http")) {
    return(NA)
  }

  # stream in a few lines only
  message("read")
  url1 <- url(link)
  if (str_ends(link, "\\.gz")) {
    temp <- readLines(gzcon(url1), n = n_row)
  } else {
    temp <- readLines(url1, n = n_row)
  }
  close(url1)
  readable <- map(temp, function(x) {all(charToRaw(x[1]) <= as.raw(127))}) %>%
    unlist() %>%
    all()
  if (!readable) {
    return(NULL)
  }

  # parsing, using fread auto
  temp_df <- tryCatch(data.table::fread(text = temp),#, header = TRUE, fill = TRUE),
                      error = function() {"parsing failed"})

  return(temp_df)
}

# load rdata to file name
load_rdata <- function(file) {
  env <- new.env()
  nm <- load(file, envir = env)[1]
  env[[nm]]
}

# Plot correlation heatmap
plot_hmap <- function (cor_mat,
                       col = clustifyr:::not_pretty_palette,
                       legend_title = NULL,
                       ...) {
  pheatmap::pheatmap(cor_mat,
                     color = colorRampPalette(col)(100),
                     ...)
}

# pull in someta
someta <- readRDS(url("https://github.com/rnabioco/someta/raw/master/inst/extdata/current_geo.rds"))
someta <- someta[ , ] %>% select(id, organism = org, usable, files = suppfiles, tar_files = tarfiles, geo, pubmed) %>%
  mutate(files = map_chr(files, function(x) paste0(x, collapse = "; "))) %>% 
  mutate(tar_files = map_chr(tar_files, function(x) paste0(x, collapse = "; "))) %>% 
  mutate(files = ifelse(str_length(files) > 0, files, "none")) %>% 
  mutate(tar_files = ifelse(str_length(tar_files) > 0 & tar_files != "error_parse", tar_files, "none")) %>% 
  mutate(usable = factor(usable, levels = c("yes", "no"))) %>% 
  mutate(summary = map_chr(geo, function(x) {
    g <- tryCatch(x$summary,
                  error = function(e) return(NULL))
    if (is.null(g)) {
      g <- "none"
    }
    if (length(g) > 0) {
      g <- str_c(g, collapse = " ")
    }
    g
  })) %>% 
  mutate(pubmed_id = map_chr(pubmed, function(x) {
    g <- tryCatch(x$pmid[1],
             error = function(e) return(NULL))
    if (is.null(g)) {
      g <- "none"
    }
    g
    })) %>% 
  mutate(pubmed_title = map_chr(pubmed, function(x) {
    g <- tryCatch(x$title[1],
                  error = function(e) return(NULL))
    if (is.null(g)) {
      g <- "none"
    }
    g
  }))



