#' Robust Self-Representation Sparse Reconstruction and Manifold Regularization
#'
#' Performs robust sparse self-representation with manifold regularization.
#'
#' @param x Numeric data matrix.
#' @param Wt Weight matrix.
#' @param L Laplacian matrix.
#' @param alpha Regularization parameter.
#' @param beta Graph regularization parameter.
#' @param epsilon Convergence threshold.
#' @param maxites Maximum number of iterations.
#'
#' @return
#' A list containing:
#' \describe{
#'   \item{Optimum.A}{Coefficient matrix}
#'   \item{Optimum.G}{Diagonal weight matrix}
#' }
#'
#' @examples
#' set.seed(6542)
#'
#' cluster1 <- matrix(
#'   rnorm(12 * 5, mean = 2, sd = 0.5),
#'   nrow = 12
#' )
#'
#' cluster2 <- matrix(
#'   rnorm(13 * 5, mean = 7, sd = 0.5),
#'   nrow = 13
#' )
#'
#' X <- rbind(cluster1, cluster2)
#'
#' wd <- diag(runif(25))
#' lp <- diag(runif(25))
#'
#' fit <- RSSRMR(
#'   x = X,
#'   Wt = wd,
#'   L = lp
#' )
#'
#' fit$Optimum.G
#'
#' @export
RSSRMR <- function(
    x,
    Wt,
    L,
    alpha = 1,
    beta = 1,
    epsilon = 0.001,
    maxites = 50
) {

  d <- ncol(x)

  opt.A <- matrix(1, nrow = d, ncol = d)

  opt.G <- diag(d)

  delta <- 1

  step <- 0

  while (delta >= epsilon && step <= maxites) {

    step <- step + 1

    old.A <- opt.A

    old.G <- opt.G

    Q <- (
      t(x) %*% Wt %*% x +
        alpha * t(x) %*% L %*% x +
        beta * old.G
    )

    Q1 <- t(x) %*% Wt %*% x

    opt.A <- solve(Q, Q1)

    aii <- diag(opt.A)

    aii[aii == 0] <- .Machine$double.eps

    opt.G <- diag(1 / (2 * abs(aii)))

    delta <- max(abs(old.A - opt.A))
  }

  list(
    Optimum.A = opt.A,
    Optimum.G = opt.G
  )
}


#' Robust Distance Weights
#'
#' Computes robust observation weights.
#'
#' @param x Numeric data matrix.
#' @param q Quantile threshold.
#'
#' @return
#' Numeric vector of weights.
#'
#' @examples
#' set.seed(123)
#'
#' x <- matrix(rnorm(50), nrow = 10)
#'
#' dweight(x)
#'
#' @importFrom robustbase covMcd
#' @importFrom stats mahalanobis qchisq
#'
#' @export
dweight <- function(x, q = 0.9) {

  p <- ncol(x)

  ch0 <- covMcd(
    x,
    nsamp = "deterministic"
  )

  mu <- ch0$center

  Sx <- ch0$cov

  Md <- mahalanobis(x, mu, Sx)

  cc <- sqrt(qchisq(q, df = p))

  ifelse(Md > cc, cc / Md, 1)
}
