#' @include mprocuste.R

#' Anova function for `pm` objects.
#'
#' @author Eric Coissac
#' @author Christelle Gonindard-Melodelima
#' @export
anova.pm = function(m, permutations = how(nperm = 999),...) {

  mf   = m$model
  coef = m$coefficients

  sdxy = sqrt(diag(m$cov))

  mt = terms(mf)

  reponse = attr(mt,"response")
  explicatives = attr(mt,'term.labels')
  nXs = length(explicatives)

  coef.norm = coef * sdxy[explicatives] / sdxy[reponse]


  cors = m$cov / outer(sdxy,sdxy)

  #print(reponse)
  #print(explicatives)

  cors.Y = cors[reponse,explicatives]

  SCT  = m$SCT
  SCR = sum(m$residuals^2)

  SCE = SCT * coef.norm * cors.Y

  names(SCE) = explicatives

  SCET = sum(SCE)

  SCIT = SCT - SCET - SCR

  SumSq  = c(SCE,Residuals=SCR)
  Df     = c(rep(1,nXs),m$df.residual)
  MeanSq = SumSq/Df
  Fvalue = c(MeanSq[-length(MeanSq)]/MeanSq[length(MeanSq)],NA)
  Pvalue = 1-pf(Fvalue,
                Df[-length(MeanSq)],
                Df[length(MeanSq)])

  result = data.frame(Df,
                      SumSq,
                      MeanSq,
                      Fvalue,
                      Pvalue)

  colnames(result)=c("Df","Sum Sq","Mean Sq","F value","Pr(>F)")


  attr(result, "heading")= paste("Analysis of Variance Table\n\nResponse:",
                                 all.vars(m$terms)[1]
  )
  class(result)=c("anova",class(result))

  return(result)
}

#' Generate permutation matrix according to a schema.
#' 
#' The permutation schema is defined using the `how` function.
#' The implementation of this function is currectly extraced 
#' from the VEGAN package and just copied pasted here to avoid
#' dependency on an hidden vegan function.
#'
getPermuteMatrix = function (perm, N, strata = NULL) 
{
  if (length(perm) == 1) {
    perm <- how(nperm = perm)
  }
  if (!missing(strata) && !is.null(strata)) {
    if (inherits(perm, "how") && is.null(getBlocks(perm))) 
      setBlocks(perm) <- strata
  }
  if (inherits(perm, "how")) 
    perm <- shuffleSet(N, control = perm)
  else {
    if (!is.integer(perm) && !all(perm == round(perm))) 
      stop("permutation matrix must be strictly integers: use round()")
  }
  if (is.null(attr(perm, "control"))) 
    attr(perm, "control") <- structure(list(within = list(type = "supplied matrix"), 
                                            nperm = nrow(perm)), class = "how")
  perm
}

