mixsespc.mle <- function(x, g = 2, tol = 1e-4) {

  fun <- function(param, x, w, I3) {
    m <- param[1:3]
    the1 <- param[4]
    the2 <- param[5]
    heta <- sqrt(the1^2 + the2^2 + 1) - 1
    m0 <- sqrt(m[2]^2 + m[3]^2)
    rl <- sum(m^2)  ## gamma^2
    x1b <- c( -m0^2, m[1] * m[2], m[1] * m[3] ) / ( m0 * sqrt(rl) )
    x2b <- c(0, -m[3], m[2])/m0
    T1 <- tcrossprod(x1b)
    T2 <- tcrossprod(x2b)
    T12 <- tcrossprod(x1b, x2b)
    vinv <- I3 + the1 * (T1 - T2) + the2 * ( T12 + t(T12) ) + heta * (T1 + T2)
    a <- as.vector( x %*% m )
    b <- Rfast::rowsums( x %*% vinv * x )
    E <- b * rl + b - a^2
    sqe <- sqrt(E)
    up <- log( b * (rl + 1) * sqe * ( atan2(sqe, -a) - atan2(sqe, a) + pi ) + 2 * a * E )
    down <- log( b * E^2 )
    - sum(w * up) + sum(w * down)
  }

  fun2 <- function(wlika, rswlika, param, x, I3, g, lika) {

    wij <- wlika / rswlika  ## weights
    pj <- Rfast::colmeans(wij)   # PANOS

    for (j in 1:g) {
      a1 <- optim(param[j, ], fun, x = x, w = wij[, j], I3 = I3, control = list(maxit = 5000))
      a2 <- optim(a1$par, fun, x = x, w = wij[, j], I3 = I3, control = list(maxit = 5000), method = "BFGS")
      while (a1$value - a2$value > 1e-05) {
        a1 <- a2
        a2 <- optim(a1$par, fun, x = x, w = wij[, j], I3 = I3, control = list(maxit = 5000))
      }
      param[j, ] <- a2$par
      m <- param[j, 1:3]
      the1 <- param[j, 4]  ;  the2 <- param[j, 5]
      heta <- sqrt(the1^2 + the2^2 + 1) - 1
      m0 <- sqrt(m[2]^2 + m[3]^2)
      rl <- sum(m^2)  ## gamma^2
      x1b <- c( -m0^2, m[1] * m[2], m[1] * m[3] ) / ( m0 * sqrt(rl) )
      x2b <- c(0, -m[3], m[2])/m0
      T1 <- tcrossprod(x1b)
      T2 <- tcrossprod(x2b)
      T12 <- tcrossprod(x1b, x2b)
      vinv <- I3 + the1 * (T1 - T2) + the2 * ( T12 + t(T12) ) +
        heta * (T1 + T2)
      a <- as.vector( x %*% m )
      b <- Rfast::rowsums( x %*% vinv * x )
      E <- b * rl + b - a^2
      sqe <- sqrt(E)
      up <- log( b * (rl + 1) * sqe * ( atan2(sqe, -a) - atan2(sqe, a) + pi ) + 2 * a * E )
      down <- log( b * E^2 )
      lika[, j] <- up - down + log(pj[j])  #PANOS
    }

    wlika <-  exp(lika) 		#PANOS
    rswlika <- Rfast::rowsums(wlika) #PANOS
    lik <- sum( log( rswlika ) ) 	#PANOS
    wij <- wlika / rswlika

    list(wij = wij, param = param, wlika = wlika, rswlika = rswlika, lika = lika, lik = lik)
  }

  n <- dim(x)[1]
  I3 <- diag(3)

  lik <- NULL
  lika <- matrix(nrow = n, ncol = g)
  param <- matrix(nrow = g, ncol = 5)

  runtime <- proc.time()
  ## Step 1

  if ( g > 1 ) {
    ## cl <- kmeans(x, g, nstart = n.start)$cl
    y <- Directional::euclid.inv(x)
    mod <- mixture::gpcm(y, G = g, mnames = NULL, start = 2, mmax = 100)
    cl <- Rfast::rowMaxs(mod$z)
  } else  cl <- rep(1, n)
  wij <- tabulate(cl)

  while ( min(wij) <= 10 ) {
    g <- g - 1
    lika <- matrix(nrow = n, ncol = g)
    param <- matrix(nrow = g, ncol = 5)
    # cl <- kmeans(x, g, nstart = n.start)$cl
    mod <- mixture::gpcm(y, G = g, mnames = NULL, start = 2, mmax = 100)
    cl <- Rfast::rowMaxs(mod$z)
    wij <- tabulate(cl)
  }

  for ( j in 1:g ) {
    mod <- Directional::sespc.mle(x[cl == j, ])
    param[j, ] <- c(mod$mu, mod$theta)
    m <- param[j, 1:3]
    the1 <- param[j, 4]  ;  the2 <- param[j, 5]
    heta <- sqrt(the1^2 + the2^2 + 1) - 1
    m0 <- sqrt(m[2]^2 + m[3]^2)
    rl <- sum(m^2)  ## gamma^2
    x1b <- c( -m0^2, m[1] * m[2], m[1] * m[3] ) / ( m0 * sqrt(rl) )
    x2b <- c(0, -m[3], m[2])/m0
    T1 <- tcrossprod(x1b)  ;  T2 <- tcrossprod(x2b)
    T12 <- tcrossprod(x1b, x2b)
    vinv <- I3 + the1 * (T1 - T2) + the2 * ( T12 + t(T12) ) + heta * (T1 + T2)
    a <- as.vector( x %*% m )
    b <- Rfast::rowsums( x %*% vinv * x )
    E <- b * rl + b - a^2
    sqe <- sqrt(E)
    up <- log( b * (rl + 1) * sqe * ( atan2(sqe, -a) - atan2(sqe, a) + pi ) + 2 * a * E )
    down <- log( b * E^2 )
    lika[, j] <- up - down
  }

  wlika <- exp(lika)
  rswlika <- Rfast::rowsums(wlika)
  #lik <- sum( log( rswlika ) )  ## initial log-likelihood

  ep <- fun2(wlika, rswlika, param, x, I3, g, lika)
  lik[1] <- ep$lik
  ep2 <- fun2(ep$wlika, ep$rswlika, ep$param, x, I3, g, ep$lika)
  lik[2] <- ep2$lik

  i <- 2
  while ( lik[i] - lik[i - 1] > tol ) {
    i <- i + 1
    ep <- ep2
    ep2 <- fun2(ep$wlika, ep$rswlika, ep$param, x, I3, g, ep$lika)
    lik[i] <- ep2$lik
  }
  res <- ep2
  if ( ep$lik > ep2$lik )  res <- ep

  pj <- Rfast::colmeans(res$wij)
  loglik <- res$lik
  ta <- Rfast::rowMaxs(res$wij)  ## estimated cluster of each observation
  param <- cbind(pj, res$param)
  runtime <- proc.time() - runtime
  colnames(param) <- c( "probs", paste("mu", 1:3, sep = ""), "theta1", "theta2" )
  rownames(param) <- paste("Cluster", 1:g, sep = " ")

  list( param = param, loglik = loglik - n * log(4 * pi^2),
        probs = res$wij, pred = ta, iters = i, runtime = runtime )
}
