BrierScore <- function(obs, pred, thresholds = seq(0, 1, 0.1)) {
  if (max(pred) > 1 | min(pred) < 0) {
    stop("Predictions outside [0,1] range. Are you certain this is a probability forecast? \n")
  } else if (max(obs) != 1 & min(obs) != 0) {
    .message("Binary events must be either 0 or 1. Are you certain this is a binary event? ")
  } else {
    nbins <- length(thresholds) - 1  # Number of bins
    n <- length(pred)
    bins <- as.list(paste("bin", 1:nbins,sep = ""))
    for (i in 1:nbins) {
      if (i == nbins) {
        bins[[i]] <- list(which(pred >= thresholds[i] & pred <= thresholds[i + 1]))
      } else {
        bins[[i]] <- list(which(pred >= thresholds[i] & pred < thresholds[i + 1]))
      }
    }

    fkbar <- okbar <- nk <- array(0, dim = nbins)
    for (i in 1:nbins) {
      nk[i] <- length(bins[[i]][[1]])
      fkbar[i] <- sum(pred[bins[[i]][[1]]]) / nk[i]
      okbar[i] <- sum(obs[bins[[i]][[1]]]) / nk[i]
    }

    obar <- sum(obs) / length(obs)
    relsum <- ressum <- term1 <- term2 <- 0
    for (i in 1:nbins) {
      if (nk[i] > 0) {
        relsum <- relsum + nk[i] * (fkbar[i] - okbar[i])^2
        ressum <- ressum + nk[i] * (okbar[i] - obar)^2
        for (j in 1:nk[i]) {
          term1 <- term1 + (pred[bins[[i]][[1]][j]] - fkbar[i])^2
          term2 <- term2 + (pred[bins[[i]][[1]][j]] - fkbar[i]) * (obs[bins[[i]][[1]][j]] - okbar[i])
        }
      }
    }
    rel <- relsum / n
    res <- ressum / n
    unc <- obar * (1 - obar)
    bs <- sum((pred - obs)^2) / n
    bs_check_res <- rel - res + unc
    bss_res <- (res - rel) / unc
    gres <- res - term1 * (1 / n) + term2 * (2 / n)   # Generalized resolution
    bs_check_gres <- rel - gres + unc                 # BS using GRES
    bss_gres <- (gres - rel) / unc                    # BSS using GRES

    #
    # Estimating the bias-corrected components of the BS 
    #
    term3 <- array(0, nbins)
    for (i in 1:nbins) {
      term3[i] <- (nk[i] / (nk[i] - 1)) * okbar[i] * (1 - okbar[i])
    }
    term_a <- sum(term3,  na.rm = T) / n
    term_b <- (obar * (1 - obar)) / (n - 1)
    rel_bias_corrected <- rel - term_a
    gres_bias_corrected <- gres - term_a + term_b
    if (rel_bias_corrected < 0 || gres_bias_corrected < 0) {
      rel_bias_corrected2 <- max(rel_bias_corrected, rel_bias_corrected - gres_bias_corrected, 0)
      gres_bias_corrected2 <- max(gres_bias_corrected, gres_bias_corrected - rel_bias_corrected, 0)
      rel_bias_corrected <- rel_bias_corrected2
      gres_bias_corrected <- gres_bias_corrected2
    }
    unc_bias_corrected <- unc + term_b
    bss_bias_corrected <- (gres_bias_corrected - rel_bias_corrected) / unc_bias_corrected

    #if (round(bs, 8) == round(bs_check_gres, 8) & round(bs_check_gres, 8) == round((rel_bias_corrected - gres_bias_corrected + unc_bias_corrected), 8)) {
    #  cat("No error found  \ n")
    #  cat("BS = REL - GRES + UNC = REL_lessbias - GRES_lessbias + UNC_lessbias  \ n")
    #}

    invisible(list(rel = rel, res = res, unc = unc, bs = bs, bs_check_res = bs_check_res, bss_res = bss_res, gres = gres, bs_check_gres = bs_check_gres, bss_gres = bss_gres, rel_bias_corrected = rel_bias_corrected, gres_bias_corrected = gres_bias_corrected, unc_bias_corrected = unc_bias_corrected, bss_bias_corrected = bss_bias_corrected, nk = nk, fkbar = fkbar, okbar = okbar, bins = bins, pred = pred, obs = obs))
  }
}
