#' Initial source code from Dynamic Functional Principal Components
#' Research report, 2012
#' @references Siegfried Hormann, Lukasz Kidzinski and Marc Hallin
#' updated here to perform the Time-varying Dynamic Functional Principal Components
#' @references ......., ......... and .........





#' For a given process \code{X} eigendecompose it's spectral density at 
#' each time point smoothly and use an inverse fourier transform to 
#' get coefficients of the optimal filter at each time point. 
#' For details please refer to Elayouty et al paper.
#'
#' @title Compute DPCA filter coefficients of the process at each time point in the series
#' @param X multivariate non-stationary time series (coefficients of the basis system used to obtain the functional data \eqn{X(u)})
#' @param sd smoothing parameter of the (Gaussian) weighting kernel necessary for smoothing the lag-h covariances over time
#' @param V inner product of chosen basis system used to approximate the functional process \eqn{X(u)} (To enusre that the spectral denisty is Hermitian for any basis system + smoothing penalty)
#' @param lags requested filter coefficients
#' @param q window for spectral density estimation as in \code{\link{sm.spectral.density}}
#' @param weights as in \code{\link{sm.spectral.density}}
#' @return principal components series at each time point
#' @param eval if TRUE 
#' @return both the principal components series and the frequency domain eigenvalues of the smooth spectral density 
#' at each time point
#' @export
sm.dprcomp <- function (X, sd=1, V = NULL, lags = -10:10, q = NULL, weights = NULL, 
                       freq = NULL, eval=FALSE) 
{
  if (!is.matrix(X)) 
    stop("X must be a matrix")
  if (!is.vector(lags) || any(!is.positiveint(abs(lags)))) 
    stop("lags must be a vector of integers")
  if (is.null(V)) 
    V = diag(dim(X)[2])
    
  n = dim(X)[1]  
  
  Time.SD = sm.spectral.density(X, Y=NULL, sd, V = V, freq = freq, q = q, weights = weights)
  E =list()
  TV.eval=list()
  for (j in 1:(n-q)) {
  	E[[j]] = freqdom.eigen(Time.SD[[j]])
  	TV.eval[[j]] <- E[[j]]$values
  	}
  
  Mmat=chol(V)
  Mmatinv=solve(Mmat)
  
  XI = list(n-q)
  result =list(n-q)
  for (j in 1:(n-q)){
    nbasis = dim(E[[j]]$vectors)[2]  
    XI[[j]] = array(0, c(length(lags), nbasis, nbasis))
    for (component in 1:nbasis) XI[[j]][, component, ] = t(exp(-(Time.SD[[j]]$freq %*% 
                                                                   t(lags)) * (0+1i))) %*% E[[j]]$vectors[, , component] %*% t(Mmatinv)/length(Time.SD[[j]]$freq)
    result[[j]] <- timedom(Re(XI[[j]][length(lags):1, , ]), lags)
    
    
  }
  
  if (eval==TRUE) {
  	list(dfpc=result,TV.eval = TV.eval)
  	} else {
  		result
  		}
 }

