###############################################################
#                                                             #
#  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. This scripts consists on two parts, this and   #
#  Traffic_buffers_def_each_norm_2.R to perferm correctly     #                                                
#  the normalization                                          #
#                                                             #
###############################################################


# Load necessary libraries
library(sf)
library(sp)
#library(mapview)
library(dplyr)
#enter variables from the terminal comand


# 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 values for normalization
field_buffer_values <- list()

# Main processing loop
for (field in traffic_fields) {
  cat("Processing:", field, "\n")

  traffic_layer <- traffic_ind %>% 
    select(all_of(field), any_of(c("geometry", "geom"))) %>% 
    st_make_valid() %>% 
    st_as_sf()

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

    # Create buffer around each observation point
    buffer_grid <- st_buffer(refined_grid_sf, dist = buffer) %>% 
      st_make_valid() %>% 
      st_as_sf()

    # Find traffic segments intersecting each buffer
    intersections <- st_intersects(buffer_grid, traffic_layer)

    # Initialize output vectors
    buffer_values <- numeric(length(intersections))

    # Calculate length-weighted average traffic index per buffer
    for (i in seq_along(intersections)) {
      ids <- intersections[[i]]
      if (length(ids) == 0) 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)

      # Compute unitless, length-weighted average index
      buffer_values[i] <- ifelse(total_length > 0, total_weighted / total_length, NA)
    }

    # Store raw buffer values for later normalization
    key <- paste0(field, "_", buffer)
    field_buffer_values[[key]] <- buffer_values

    # Attach results to grid and save
    result_grid <- refined_grid_sf %>% 
      mutate(buffer_value = buffer_values)

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

# Normalize all field-buffer combinations independently
for (field in traffic_fields) {
  for (buffer in buffer_sizes) {
    key <- paste0(field, "_", buffer)
    values <- field_buffer_values[[key]]
    min_val <- min(values, na.rm = TRUE)
    max_val <- max(values, na.rm = TRUE)

    fname <- paste0("traffic_", field, "_buffer_", buffer, "m_norm_BCN.RDS")
    grid_data <- readRDS(file.path(wdir3, fname))

    # Unitless normalization to 0-100 scale
    grid_data$normalized <- (grid_data$buffer_value - min_val) / 
                            (max_val - min_val) * 100

    saveRDS(grid_data, file.path(wdir3, fname))
  }
}

# Combine into final dataframe by buffer
buffer_dfs <- list()
for (buffer in buffer_sizes) {
  result_df <- refined_grid_sf %>% 
    mutate(Station = row_number())

  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)
  }

  result_df[[paste0("buffer_", buffer, "m")]] <- rowMeans(norm_matrix, na.rm = TRUE)
  buffer_dfs[[as.character(buffer)]] <- result_df
}

# Use the first buffer_df as the base
combined <- buffer_dfs[[1]]

# For each of the remaining buffer_dfs, add columns to combined
for (i in 2:length(buffer_dfs)) {
  df <- buffer_dfs[[i]]
  
  # Ensure they are ordered the same and aligned geometrically
  stopifnot(all.equal(st_geometry(combined), st_geometry(df)))

  # Extract only buffer columns
  buffer_cols <- grep("^buffer_", names(df), value = TRUE)

  # Add to combined
  combined[buffer_cols] <- df[buffer_cols]
}

# Done — no joins, no coalesce needed
final_df <- st_as_sf(combined)
saveRDS(final_df, file.path(wdir2, "traffic_normalized_buffers_AQMS_nu.RDS"))