library("tidyverse")
library("traitdata")

# Match names
traits = traitdata::elton_mammals
names_unique = unique(traits$scientificNameStd)

pb = txtProgressBar(min = 0, max = length(names_unique), style = 3)
trait_names_matched = lapply(seq_along(names_unique), function(i){
  tryCatch({
    name = names_unique[i]
    setTxtProgressBar(pb, i)
    
    match_result = Symobio::gbif_match_name(name = name)
    if(match_result$status != "ACCEPTED"){
      match_result = Symobio::gbif_match_name(usageKey = match_result$acceptedUsageKey)
    }
    match_result$name_orig = name
    return(match_result)  
  }, error = function(e){
    return(NULL)
  })
}) %>% bind_rows()
close(pb)

traits_matched = trait_names_matched %>% 
  dplyr::select("name_orig", "species", "scientificName") %>% 
  dplyr::distinct() %>% 
  dplyr::inner_join(traits, by = c("name_orig" = "scientificNameStd"))

save(traits_matched, file = "data/r_objects/traits_matched.RData")

# Clean trait data
diet_cols = c("Diet.Inv", "Diet.Vend", "Diet.Vect", "Diet.Vfish", "Diet.Vunk", "Diet.Scav", "Diet.Fruit", "Diet.Nect", "Diet.Seed", "Diet.PlantO")
strata_cols = c("ForStrat.Value")
activity_cols = c("Activity.Nocturnal", "Activity.Crepuscular", "Activity.Diurnal")
bodymass_cols = c("BodyMass.Value")

traits_proc = traits_matched %>% 
  mutate(match_genus = stringr::str_detect(species, Genus),
         match_epithet = stringr::str_detect(species, Species)) %>% 
  dplyr::group_by(species) %>% 
  dplyr::group_modify(~ {
    if (nrow(.x) == 1) { 
      return (.x)
    }
    x_mod = .x
    while (nrow(x_mod) > 1){
      if(any(isFALSE(x_mod$match_genus))){
        x_mod = dplyr::filter(x_mod, isTRUE(match_genus))
        next
      }
      
      if(any(isFALSE(x_mod$match_epithet))){
        x_mod = dplyr::filter(x_mod, isTRUE(match_epithet))
        next
      }
      
      x_mod = x_mod[1,]
    }
    
    if(nrow(x_mod) == 1){
      return(x_mod)
    } else {
      return(.x[1,])
    }
  }) %>% 
  dplyr::select(c("species", diet_cols, strata_cols, activity_cols, bodymass_cols))

save(traits_proc, file = "data/r_objects/traits_proc.RData")

# Calculate Distances
library("vegan")

load("data/r_objects/range_maps.RData")
load("data/r_objects/traits_proc.RData")

target_species = unique(range_maps$name_matched[!is.na(range_maps$name_matched)])
traits_target = dplyr::filter(traits_proc, species %in% target_species)
  
# some pre-processing
traits_target$`ForStrat.Value` = as.numeric(factor(traits_target$`ForStrat.Value`, levels = c("G", "S", "Ar", "A")))
traits_target$`BodyMass.Value` = scale(log(traits_target$`BodyMass.Value`))

diet_dist = vegan::vegdist(traits_target[,diet_cols], "bray")
foraging_dist = dist(traits_target[,strata_cols])
activity_dist = vegan::vegdist(traits_target[,activity_cols], "bray")
bodymass_dist = dist(traits_target[,bodymass_cols])

func_dist = (diet_dist + foraging_dist/max(foraging_dist) + activity_dist + bodymass_dist/max(bodymass_dist)) / 4
names(func_dist) = traits_target$species
func_dist = as.matrix(func_dist)

save(func_dist, file = "data/r_objects/func_dist.RData")