#' Read log file
#' 
#' @param path log file path
#' @return Parsed tibble of log file in \code{path}
#' @importFrom fs path path_ext
#' @importFrom readr read_file read_lines
#' @importFrom jsonlite parse_json
#' @importFrom dplyr as_tibble filter select select_if rename_all mutate
#' @importFrom tidyr unnest
#' @importFrom purrr map map_chr discard
#' @importFrom stringr str_replace str_extract str_remove str_split str_trim
#' @importFrom rlang .data
#' @export
#' @examples 
#' \dontrun{
#' rcg <- read_log("data/20220405162804-HELIOS_base_3-vs-enemy_2.rcg")
#' rcl <- read_log("data/20220405162804-HELIOS_base_3-vs-enemy_2.rcl")
#' }
read_log <- function(path) {
  ext <- path |> path() |> path_ext()
  
  if (ext == "rcg") {
    return(read_rcg(path))
  }
  if (ext == "rcl") {
    return(read_rcl(path))
  }
  
  stop("Not supported format: ", path)
}

filter_rcg <- function(rcg, type) {
  filtered <- rcg |>
    filter(.data$type == (!!type)) |>
    select_if(~ !all(is.na(.x)) && !all(is.null(unlist(.x)))) |>
    select(!type)
  
  return(filtered)
}

#' @rdname read_log
#' @export
read_rcg <- function(path) {
  parsed <- path |>
    read_file() |>
    parse_json(simplifyVector = TRUE, flatten = TRUE) |>
    as_tibble()
  
  rcg <- list(
    header = parsed |>
      filter_rcg("header") |>
      as.list(),
    
    server_param = parsed |>
      filter_rcg("server_param") |>
      rename_all(str_remove, "params.") |>
      as.list(),
    
    player_param = parsed |>
      filter_rcg("player_param") |>
      rename_all(str_remove, "params.") |>
      as.list(),
    
    player_type = parsed |>
      filter_rcg("player_type") |>
      rename_all(str_remove, "params."),
    
    team = parsed |>
      filter_rcg("team") |>
      unnest(.data$teams),
    
    show = parsed |>
      filter_rcg("show") |>
      unnest(.data$players) |>
      rename_all(str_replace, "[.]", "_"),
    
    msg = parsed |>
      filter_rcg("msg")
  )
  
  return(rcg)
}

#' @rdname read_log
#' @export
read_rcl <- function(path) {
  rcl <- path |>
    read_lines() |>
    as_tibble() |>
    mutate(
      time     = .data$value |> str_extract("\\d+") |> as.numeric(),
      agent    = .data$value |> str_extract("\\w+_([0-9]{1,2}|Coach)(?!\\))"),
      team     = .data$agent |> str_remove("_([0-9]{1,2}|Coach)"),
      unum     = .data$agent |> str_extract("([0-9]{1,2}|Coach)$"),
      commands = .data$value |>
        str_extract("\\(.+\\)$") |>
        map(
          ~ .x |>
            str_split("\\(|\\)", simplify = TRUE) |>
            str_trim() |>
            discard(~ .x == "")),
    ) |>
    unnest(.data$commands) |>
    mutate(
      splited = .data$commands |> str_split("\\ ", n = 2),
      command = .data$splited |> map_chr(1),
      args    = .data$splited |> map(~ .x[-1]),
    ) |>
    select(
      .data$time,
      .data$team,
      .data$unum,
      .data$command,
      .data$args
    )
  
  return(rcl)
}
