#' Reorder the rows and columns of factor pattern matrix
#'
#' @param A Factor Pattern matrix or an object with $loadings.
#' @param unclass = 1 to unclass the result
#' @param sortcols = 0 not to sort factors (columns of A) according to
#' factor contributions.
#' @param print = 1 to print the result
#'
#' @details
#' First, if sortcols == 1, the columns of \code{A} are reordered
#' according to the magnitude of \code{diag(t(A)\%*\%A)}. \cr
#' Then, for each row, the column number of the maximum elements of
#' \code{abs(A)}
#' is recorded (as \code{max.col(abs(A))}) and the rows of \code{A}
#'are sorted according
#' to these column numbers. \cr
#' Finally, within each max.col group, the rows are again sorted
#' according to the magnitude of \code{A}.
#'
#' @examples
#' set.seed(1701)
#' n <- 20; ndim <- 4
#' A0 <- matrix(runif(n*ndim),n,ndim)
#' dimnames(A0)=list( paste("v",1:n,sep=""),paste("f",1:ndim,sep=""))
#' A0v <- varimax(A0)$loadings
#' A0v <- A0v*matrix(sample(c(-1,1,1),n*ndim,replace=TRUE),n,ndim)
#' A0v[,3:4] <- -A0v[,3:4]
#'
#' resrc <- reorder_fa(A0v)
#' A0vrc <- resrc$loadings
#' Print(A0v,A0vrc, fmt="6.3", fuzz=0.7)
#'
#' resr <- reorder_fa(A0v, sortcols=0)
#' A0vr <- resr$loadings
#' Print(A0v,A0vr, fmt="6.3", fuzz=0.7)
#'
#' # reordered matrix from original
#' dif1 <- A0vrc-A0v[resrc$row_order,resrc$col_order]
#'
#' # original from reordered matrix
#' A0v2 <- A0vrc; A0v2[resrc$row_order,resrc$col_order] <- A0vrc
#' rownames(A0v2)[resrc$row_order] <- rownames(A0vrc)
#' Print(A0v,A0v2, fmt="6.3")
#' dif2 <- A0v2-A0v
#' Print(dif1, dif2)
#'
#' # reducing the number of negative signs
#' A0vrcs <- reflect_fa( A0vrc )$loadings
#' Print(A0vrc, A0vrcs, fmt="6.3")
#'
#' # attributes
#' print(reorder_fa(A0v)$loadings)
#' print(reorder_fa(A0v, unclass=1)$loadings)
#'
#' @return A list of \cr
#' loadings = reordered loadings matrix \cr
#' row_order = sort order of the rows \cr
#' col_order = sort order of the cols
#'
#' @export
#'

reorder_fa <- function( A, unclass=0, sortcols=1, print=0 ){
 # reordering the rows of A as  proc factor reorder
 # Shin-ichi Mayekawa
 # 20140528
 # non matrix input: 20140612
 # renamed as reorder_fa: 20150705
 # sort by factor contributions: 20151215 (no implementation)
 # attributes, unclass: 20151215
 # names and sortcols: 20151224
 # roxygen: 20210421
 #

 # store attributes
 attrib=attributes(A)
 A=unclass(A)
 n=nrow(A)

  # names
 if( is.null(rownames(A)) ) rownames(A)=paste("r",1:nrow(A),sep="")
 if( is.null(colnames(A)) ) colnames(A)=paste("c",1:ncol(A),sep="")
 rname=rownames(A); cname=colnames(A)

 odc=1:ncol(A)
 names(odc)=cname
 if( sortcols == 1 ){
  # sort by diag(t(A)%*%A)
  fc=colSums(A*A)
  names(fc)=cname
  odc=order(-fc)
  A=A[,odc]
  cname=colnames(A)
 }

 # sort according to the location(col. number) of the row maximum
 maxcol=max.col(abs(A))

 index=1:n
 od=order(maxcol)
 B=A[od,]
 index=index[od]
 maxcols=maxcol[od]
 # rownames(B)=name[od]
 rname=rownames(B)

 um=unique(maxcols)
 num=length(um)

 # sort according to the value of A within the subgroups
 for( i in 1:num ){
  umi=um[i] # subgroup id = column number
  loc=which(maxcols == umi)
  od=order(-(B[loc,umi]))
  B[loc,]=B[loc,,drop=0][od,,drop=0]
  rname[loc]=rname[loc][od]
  index[loc]=index[loc][od]
 }
 rownames(B)=rname

 if( print > 0 ){
  cat("\nReordered Matrix\n")
  Print(index,B,fmt="3.0 6.2")
 }

 if( !unclass ){
  dn=dimnames(B)
  attributes(B)=attrib
  dimnames(B)=dn
 }

 return( list( loadings=B, row_order=index, col_order=odc ) )

} # end of reorder_fa



