###############################################################
#                                                             #
#  Step-by-Step Script to Calculate Traffic Density buffers   #                                                             
#                                                             #
#  Computes the traffic buffer index for each categorya and   #
#  then calculates the normalization based on the whole       #
#  categories.                                                #
#                                                             #
###############################################################


# Load necessary libraries
library(sf)
library(sp)
#library(mapview)
library(dplyr)

# Load traffic data
wdir <- "/esarchive/scratch/ajulian/scripts/Open_Data/Traffic_MPCS/Data"
wdir2 <- "/esarchive/scratch/ajulian/scripts/Open_Data/Traffic_MPCS/Results"
wdir3 <- "/esarchive/scratch/ajulian/scripts/Open_Data/Traffic_MPCS/Results/temporal"
wdir4 <- "/esarchive/scratch/ajulian/scripts/Open_Data/Traffic_buffers/Data"

# Define CRS values
crs_utm <- "+proj=utm +zone=31 +ellps=intl +units=m +no_defs"
crs_latlon <- "+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0"

# Load spatial data
traffic_ind <- readRDS(file.path(wdir2, "traffic_ind_CAT_2024p.RDS"))
refined_grid_sf <- readRDS(file.path(wdir4, "sp_obs_locations.RDS"))
refined_grid_sf <- st_as_sf(refined_grid_sf, coords = c("longitude", "latitude"), crs = 4326)

# Transform CRS to UTM 31N
traffic_ind <- st_transform(traffic_ind, crs_utm)
refined_grid_sf <- st_transform(refined_grid_sf, crs_utm)

# Define traffic fields
group_im <- c("im_manana", "im_tarde", "im_noche")
group_imd <- c("imd_finde", "imd_verano", "imd_no_verano_laborable", "imd_total")
traffic_fields <- c(group_im, group_imd)

# Buffer sizes (meters)
buffer_sizes <- c(5, 10, 15, 25, 50, 100, 300, 500, 1000, 2000, 5000, 10000)

# Store field-buffer raw values for normalization (per field: vector concatenant tots els buffers)
field_all_buffers_values <- list()

# ================================
# PAS 1: Calcula totes les densitats i guarda en una llista per variable (concatenant tots buffers)
# ================================
for (field in traffic_fields) {
  cat("Processing:", field, "\n")

  traffic_layer <- traffic_ind %>% 
    select(all_of(field)) %>% 
    st_make_valid() %>% 
    st_as_sf()

  # Inicialitza vector gran per a guardar tots valors buffers concatenats
  all_values_field <- numeric()

  # Guarda els valors per buffer (per guardar després)
  buffer_values_list <- list()

  for (buffer in buffer_sizes) {
    cat(" Buffer:", buffer, "m\n")

    buffer_grid <- st_buffer(refined_grid_sf, dist = buffer) %>% 
      st_make_valid() %>% 
      st_as_sf()

    intersections <- st_intersects(buffer_grid, traffic_layer)
    buffer_values <- numeric(length(intersections))

    for (i in seq_along(intersections)) {
      ids <- intersections[[i]]
      if (length(ids) == 0) {
        buffer_values[i] <- NA
        next
      }

      lines <- traffic_layer[ids, ]
      lines$length_m <- as.numeric(st_length(lines))
      lines$weighted <- lines[[field]] * lines$length_m

      total_weighted <- sum(lines$weighted, na.rm = TRUE)
      total_length <- sum(lines$length_m, na.rm = TRUE)

      buffer_values[i] <- ifelse(total_length > 0, total_weighted / total_length, NA)
    }

    buffer_values_list[[as.character(buffer)]] <- buffer_values
    all_values_field <- c(all_values_field, buffer_values)
  }

  # Guarda tots els valors concatenats per aquesta variable
  field_all_buffers_values[[field]] <- list(
    all_values = all_values_field,
    buffer_values = buffer_values_list
  )
}

# ================================
# PAS 2: Normalitza globalment per variable (concatenant tots buffers) i guarda arxius
# ================================
for (field in traffic_fields) {
  cat("Normalizing:", field, "\n")

  all_values_field <- field_all_buffers_values[[field]]$all_values
  min_val <- min(all_values_field, na.rm = TRUE)
  max_val <- max(all_values_field, na.rm = TRUE)

  for (buffer in buffer_sizes) {
    buffer_values <- field_all_buffers_values[[field]]$buffer_values[[as.character(buffer)]]

    normalized_values <- (buffer_values - min_val) / (max_val - min_val) * 100
    normalized_values[is.na(buffer_values)] <- NA  # Manté NA

    result_grid <- refined_grid_sf %>% 
      mutate(buffer_value = buffer_values,
             normalized = normalized_values)

    fname <- paste0("traffic_", field, "_buffer_", buffer, "m_norm_BCN.RDS")
    saveRDS(result_grid, file.path(wdir3, fname))
  }
}

# ================================
# PAS 3: Combina totes les normalitzacions per buffer en refined_grid_sf
# ================================
refined_grid_sf <- refined_grid_sf %>% mutate(Station = row_number())

for (buffer in buffer_sizes) {
  norm_matrix <- matrix(NA, nrow = nrow(refined_grid_sf), ncol = 0)
  
  for (field in traffic_fields) {
    fname <- paste0("traffic_", field, "_buffer_", buffer, "m_norm_BCN.RDS")
    grid_data <- readRDS(file.path(wdir3, fname))
    norm_matrix <- cbind(norm_matrix, grid_data$normalized)
  }

  col_name <- paste0("buffer_", buffer, "m_normalized")
  refined_grid_sf[[col_name]] <- rowMeans(norm_matrix, na.rm = TRUE)
}

# ================================
# PAS 4: Crea índex compost 100-300-500 m
# ================================
buffer_distances <- c(100, 300, 500)
buffer_cols <- paste0("buffer_", buffer_distances, "m_normalized")

missing_cols <- setdiff(buffer_cols, names(refined_grid_sf))
if (length(missing_cols) > 0) {
  stop("Missing buffer columns: ", paste(missing_cols, collapse = ", "))
}

df_buf <- refined_grid_sf %>%
  st_drop_geometry() %>%
  select(all_of(buffer_cols)) %>%
  mutate(across(everything(), as.numeric))

area_weights <- 1 / (pi * buffer_distances^2)
normalized_weights <- area_weights / sum(area_weights)
composite_index <- as.numeric(as.matrix(df_buf) %*% normalized_weights)

refined_grid_sf$traffic_100_300_500 <- composite_index

# ================================
# PAS 5: Guarda resultat final
# ================================
saveRDS(refined_grid_sf, file.path(wdir2, "traffic_buffers_AQMS_combined_all.RDS"))
