#' Calculate the Covariance of the Spectral Principal Component Scores
#'
#' This function estimates the (theoretical) autocovariance for each spectral
#' principal component score for some spatial functional data.
#' @param FS the spectral density.
#' @param L the maximum lag to compute the covariance of the scores
#' @return A list with components \item{laglist}{the list of lags.} \item{cov}{a
#'   matrix with the autocovariances of the principal component scores.}
#' @seealso \code{\link{fsd.spca}}, \code{\link{fsd.spca.var}}
#' @details To ensure accuracy of numerical integration during the Fourier
#'   transform, the frequencies of \code{F} should be a suitably dense grid.
#' @keywords fsd
#' @export

fsd.spca.cov = function (FS, L = 3)
{
  if (!inherits(FS, "fsd.freqdom"))
    stop("FS needs to be a spectral density operator")

  if (length(L) == 1)
    L = rep(L, length(FS$freq[[1]]))

  if (length(L) != length(FS$freq[[1]]))
    stop("Dimensions incompatible")

  if (!is.null(FS$basis)) {
    B = inprod(FS$basis, FS$basis)
  } else {
    B = diag(dim(FS$operators[[1]])[1])
  }
  B.root = eigen(B)$vectors %*% diag(sqrt(eigen(B)$values)) %*%
    t(eigen(B)$vectors)
  for (i in 1:length(FS$operators)) {
    FS$operators[[i]] = B.root %*% FS$operators[[i]] %*% B.root
  }

  FS.E = sapply(FS$operators,
               function(w) {eigen(w, symmetric = TRUE,
                                  only.values = TRUE)$values},
               simplify="array")

  FS.E = array(FS.E, dim = c(1, dim(FS.E)))

  laglist = unfold(lapply(L, function(h) {-h:h}))

  filters = fsd.fourier.inverse(FS.E, FS$freq, laglist)

  covs = array(unlist(filters$operators),
               dim = c(dim(FS.E)[2], length(filters$operators)),
               dimnames = list(paste("PC", 1:dim(FS.E)[2]), NULL))

  list(laglist = laglist, cov = covs)
}
