# get_track_data.r

## https://developer.spotify.com/web-api/get-track/

## SPOTIFY CAN HANDLE MULTIPLE track ids AT A TIME. (less than 300 per batch)
## But then how would we store them? 
if (FALSE) {
  track_uris <- runQry("SELECT track_uri FROM staging_raw_spotify_v2 limit 1000", all.pfm=T) %>% {.$track_uri}
  track_ids <- parse_spotify_uri(track_uris)[!is.na(track), track]
  track_ids <- track_ids[1:151]
  url <- get_url_for_spotify_API (track_uris[[1]]) %>% dirname %>% sprintf("%s/?ids=%s", ., pasteC(track_ids, C=","))
  raw_json <- get_json_from_spotify_url(url, parse=FALSE, saveToDir=FALSE)
}

get_track_data <- function(uri, parsed_json='use only if uri is missing'
  , token=get_spotify_API_token(), envir.token=parent.frame()
  , file.process_tracking=src.p("processed", "tracks_processed.txt")
  , jesus=TRUE
  , gitcommit=(is.null(file.process_tracking))
  , verbose.fetching=verbose, verbose.writing=verbose, verbose.jesus=FALSE, verbose.processing=verbose, verbose=TRUE
  ) {

## When uri is given, the result will be saved as a '.tsv' as well, regardless of jesus value


  # if (!missing(uri) && !missing(parsed_json))
  #   stop ("only one of uri and parsed_json should be given explicitly")
  # if (missing(uri) && missing(parsed_json))
  #   stop ("exactly one of uri and parsed_json should be given explicitly")
  if (!xor(missing(uri), missing(parsed_json)))
    stop ("exactly one of uri and parsed_json should be given explicitly")

  ## Check that token is not expired; if so, refresh it
  token %<>% confirm_spotify_token(envir=envir.token)
  
  if (!missing(uri)) {
    if (length(uri) > 1) {
      ARGS <- collectArgs(except=c("uri", "parsed_json"))
      return(lapply(uri, function(u) do.call(get_track_data, c(list(uri=u), ARGS))) %>% rbindlist(fill=TRUE, use.names=TRUE))
    }

    ## check if it looks like a uri or url. If not, treat it as a track.id
    if (!grepl("^(https?|spotify):", uri))
      uri %<>% get_url_for_spotify_API(track.id=.,)

    verboseMsg(verbose.processing, "Processing uri  =  ", uri, func="message", minw=-15)
    parsed_json <- get_json_from_spotify_url(uri, token=token, envir.token=envir.token, failOnError=TRUE, verbose.writing=verbose.writing, verbose.fetching=verbose.fetching)
  }

  multi_col_elements <- c("album", "artists", "external_ids", "external_urls", "href", "available_markets", "preview_url")
  as.data.table(parsed_json[names(parsed_json) %ni% multi_col_elements])

  ## external_urls
  DT.external_urls <- parse_external_url_subjson(parsed_json, recursive=TRUE)

  ## confirm owner uri is as expected
  .confirm_uri(type=parsed_json$type, id=parsed_json$id, uri=parsed_json$uri, what.confirming="track parsed_json", cleanid=TRUE, showWarnings=TRUE, verbose=FALSE)


  ## THE REST -- DT.base_ret
  single_col_elements <- setdiff(names(parsed_json), multi_col_elements)

  ## SANITY-CHECK, Specificly for track data
  if (!identical(wh.unexpected <- setdiff(names(parsed_json), single_col_elements), c("external_urls", "followers", "href")))
    warning(warningCols("There were unexpected elements in track: ", wh.unexpected))

  ## confirm all are exactly of length 1 and not a list, except for 'description'
  if (any(wh.err <- !sapply(parsed_json[single_col_elements], function(x) length(x) == 1 && !is.list(x)))) {
    # if (identical(nwhich(wh.err), "description") && 0 == length(parsed_json$description))
    #   parsed_json$description <- ""
    # else
      warning(warningCols("Some elements of the parsed_json are either not of length 1 or they are a list:", wh.err))
  }
  
  ## convert the remaining singletons to a data.table, then clean the DT slightly
  DT.base_ret <- as.data.table(parsed_json[single_col_elements])

  DT.base_ret %>% sapply(is.logical) %>% nwhich %>% {if (length(.)) setnames(DT.base_ret, old=., new=paste0("is_", .))}
  # DT.base_ret %>% setnames_addPreface("playlist", ".")

  ## confrim rows
  confirm_expected_rows(DT.base_ret, 1)
  confirm_expected_rows(DT.followers, 1)
  confirm_expected_rows(DT.external_urls, 1)

  ## Capture the names for the DT and the tsv file
  ## Note regarding slah -- There was a playlist name that had a strangling slash.  I inserted this gsub line to remove it.  It stopped working seemingly suddently. Removed the gsub line
  ##  playlist_name <- tryCatch(DT.base_ret$name[[1]] %>% spaceToUnderscore %>% gsub(",|\\!|\\?", "", .) %>% cleanChars %>% substr(1, 50), error=function(e) {warning(call.=FALSE, "Creating playlist_name failed for uri = ", uri, "' with error: ", e$message); return ("__unknown_name_due_to_error__")})
  ##  DT.nm <- sprintf("DT.%s_%s", playlist_name, DT.base_ret$id[[1]])
  ##  f.basename <- paste0(playlist_name, "_", UTC_to_human(parsed_json$api.timestamp)) [[1]]
  ## ----
  ## UPDATE: No need to use the actual playlist name. It is often filled with garbage characters anyway. Just use the ID
  track_id <- valueIfErr(DT.base_ret$id[[1]], timeStamp("Unknown_TrackID", seconds=TRUE))
  DT.nm <- sprintf("DT.trackmeta_%s", track_id)
  f.basename <- paste0("trackid-", track_id, "_", UTC_to_human(parsed_json$api.timestamp)) [[1]]

  browser(expr=inDebugMode("get_track_data"), text="in get_track_data before combining the elements using cbind")

   , markets = vec_to_csv(items$track$available_markets)

  envir <- environment()
  assign(DT.nm, envir=envir, value={
    cbind(
      DT.base_ret
    , DT.followers
    , DT.external_urls
    ) %>% setnames_addPreface("track", ".")
  })

  # ## Commenting out to run quicker
  # broswer (expr=inDebugMode("get_track_data"), text="in get_track_data() right after assigning, before saving/writing to disk")

  if (jesus)
    f.out.DT <- jesusForData(objNames=DT.nm, envir=envir, git=gitcommit, verbose=verbose.jesus, verbose.git=verbose.jesus)
    ## nothing is actually done with f.out.DT
  

  if (!missing(uri)) {

    ## update the processed file
    if (!is.null(file.process_tracking)) {
      if (!file.exists(file.process_tracking))
        initialize_file_for_process_tracking(file.process_tracking)
      writeUTF8(uri, file=file.process_tracking, append=TRUE, sep="\n")
    }

    # url <- get_url_for_spotify_playlist_data(uri, verbose=FALSE)
    # subfolder <- as.path("parsed_json", url_to_file_path(url))
    subfolder <- uri %>% get_url_for_spotify_API(verbose=FALSE) %>% url_to_file_path %>% as.path("parsed_json", .)
    f.out.tsv <- writeDT(DT=get(DT.nm), subfolder=subfolder, base=f.basename, ext="tsv", sep="\t", fileEncoding="UTF-8")  ## REMEMBER NOT TO USE CSV, since some columns are csv
    # verboseMsg(verbose, DT.nm, " written to: ", f.out.tsv, func='message', time=FALSE, minw=-15)
    verboseMsg(verbose, "Denormalized playlist data written to: ", f.out.tsv, func='message', time=FALSE, minw=-15)
  }

  return(invisible(get(DT.nm)))
}