#' Print Super Matrix ( Partitioned Matrix, Block Matrix ) with Separators.
#'
#' @param smat   input super matrix with SMdim attributes
#' @param fmt    format specification of the form: name & width & . & dicimal
#' @param nrows  a vector consisting of the # of rows of each sub matrix
#' @param ncols  a vector consisting of the # of columns of each sub matrix
#' @param sep    separator character
#' @param debug  = 1 to debug
#'
#' @details
#'  This function prints the input partitioned matrix with separator spaces
#'  and returns it invisibly (via invisible(x)).  \cr
#'  Therefor, it can be used with a pipe operator. \cr
#'  For the partitioned matrices with supermatrix attributes,
#'  see the description of supermat, getSM, or modSM.
#'
#' @examples
#' SM <- demomat(c(2,3,4),c(1,2,4),supermat=1)
#' SMc <- demomat(c(2,3,4),c(1,2,4),supermat=1, root="a")
#'
#' Printb( SM )
#' Printb( SM, sep="." )
#' Printb( SMc, fmt="8.0" )
#'
#' attributes(SM)$SMdim=NULL
#' Printb( SMc, fmt="5", nrows=c(2,3,4), ncols=c(1,2,4))
#' Printb( SMc, fmt="5", nrows=c(3,3,3), ncols=c(2,2,2,1))
#'
#' # with pipe
#' bigS <- demomat(c(2,3,4),c(1,2,4),supermat=1, root="a")  |>  printb()
#' print(bigS)
#'
#' @export
#'

Printb <- function( smat, fmt=NULL, nrows=NULL, ncols=NULL, sep=""
                    , debug=0 ){
 # print block matrix with separation lines
 # Shin-ichi Mayekawa
 # 20200523,24
 # get rid of getSM: 20200526
 # simple Print with original name: 20200527
 # return invisible(smat): 20240626
 # bugfix when smat=demomat(2,2): 20240626
 # printb as an alias: 20240626
 # warning: 20250315
 #
 
 decomp_fmt <- function( fmt=NULL, debug=1 ){
  # decompose format string of type:  NameWidth.Digits
  # Shin-ichi Mayekawa
  # 121223c
  # 130103
  #
  # Assuming fmt has a structure: name + width + dot + digits,
  # return the vector consisting of name, width, and digits
  #
  # The default name is "f".
  #   If fmt = ".5",  name="f", width="", digits="5".
  #
  #  fmt is a scalar, not a vector.
  #
  # We could execute formatC from here if we check all the 2^3 possible
  # combinations of fmt[1] -- fmt[3]
  #
  
  digits=""
  format=""    # defailt format name when nothing is given.
  width=""
  fwd=c("","","")
  if( is.null(fmt) ){
   
   # remove digits, if any.
   res=strsplit( fmt, split="\\." )[[1]]
   if( debug > 0 )
    cat("\n decomp_fmt:1", "length(res)=", length(res), " res=", res, "\n")
   if( length(res) >= 1 ){
    digits=res[2]
    res=res[-2]
   }
   if( debug > 0 )
    cat(" decomp_fmt:1", "res=", res, "\n")
   
   # if there are no name, use "f" as default and return
   if( length(grep("[[:alpha:]]", res)) == 0 ){
    format="f"
    width=res
    if( debug > 0 )
     cat(1.5, res, format,width,digits,"\n")
    fwd[1]=format; fwd[2]=width; fwd[3]=digits
    return( fwd )
   }
   
   # If res contains "fg", return
   res=strsplit( res, split="fg", fixed=1 )[[1]]
   if( debug > 0 )
    cat(" decomp_fmt:2", "length(res)=", length(res), " res=", res, "\n")
   if( length(res) >= 1  & res[1] == "" ){
    # the first element of strsplit("fg5","fg")[[1]] is NA.
    format="fg"
    width=res[2]
    fwd[1]=format; fwd[2]=width; fwd[3]=digits
    if( debug > 0 )
     cat(" decomp_fmt:2", "res=", res, "fwd=", fwd, "\n")
    return( fwd )
   }
   
   # Other format type than "fg".
   format=substr(res[1],1,1)
   res=strsplit( res, split="[defgisEG]", fixed=0 )[[1]]
   if( debug > 0 )
    cat(" decomp_fmt:3", "length(res)=", length(res), " res=", res, "\n")
   if( length(res) >= 1 ){
    if( res[1] != "" ) format="f"
    width=res[2]
   }
  }
  
  # old fortran I format.
  if( toupper(format) == "I" ) format="d"
  if( toupper(format) == "A" ) format="s"
  fwd[1]=format; fwd[2]=width; fwd[3]=digits
  
  if( debug > 0 )
   cat(" decomp_fmt:final", "fwd=", fwd, "\n")
  return( fwd )
  
 } # end of decomp_fmt
 
 
 
 
 ################################################################
 
 # error
 if( is.matrix(fmt) ){
  cat("\nwarning1(Printb): Can print only one matrix.\n\n")
 }
 
 
 # name of the matrix to be printed
 name=as.character(substitute(smat))
 
 if( !is.null(fmt) ){
  # format specification
  ff=decomp_fmt( fmt, debug=0 )
  ff[is.na(ff)]=0
  ff[ff==""]=0
  fname=ff[1]
  fwidth=as.numeric(ff[2])
  fdigits=as.numeric(ff[3])
 }
 
 # Print(ff)
 
 # nrows and ncols
 if( !is.null(nrows) & !is.null(ncols) ){
  if( !(sum(nrows) == nrow(smat) & sum(ncols) == ncol(smat)) ){
   cat("\n\nerror1:(Printb) sum(nrows) and sum(ncols) must equal to"
       , " the nrow and ncol of the input matrix. \n\n")
   return( invisible(smat) )
  }
  attributes(smat)$SMdim=list(nrows=nrows,ncols=ncols)
 }
 else if( !is.null(attributes(smat)$SMdim) ){
  nrows=attributes(smat)$SMdim$nrows
  ncols=attributes(smat)$SMdim$ncols
  # Print(nrows,ncols,rr,rc)
  #
 }
 else{
  cat(name,"\n")
  print(smat)
  return( invisible(smat) )
 }
 
 # range of each submatrix
 rr=get_range(nrows)
 rc=get_range(ncols)
 
 # # of submatrices
 nsmr=length(nrows)
 nsmc=length(ncols)
 
 # row and colnames
 rnames=rownames(smat)
 if( is.null(rnames) ) rnames=paste("r",1:sum(nrows),sep="")
 cnames=colnames(smat)
 if( is.null(cnames) ) cnames=paste("c",1:sum(ncols),sep="")
 
 nr=nrow(smat)
 nc=ncol(smat)
 
 if( debug ){
  Print(nrows, ncols, rr, rc, nsmr, nsmc, rnames, cnames, nr, nc)
 }
 
 # format the input: convert from numeric to character
 if( is.null(fmt) ){
  smatf=format( smat )
 }
 else{
  smatf=formatC( smat,format=ff[1], width=fwidth, digits=fdigits)
 }
 # If we formatC a character matrix, we will loose its attributes
 attributes(smatf)$SMdim=list(nrows=nrows,ncols=ncols)
 
 if( debug ){
  Print(smatf)
 }
 
 # add separator
 M=matrix(sep,nr+nsmr-1,nc+nsmc-1)
 Rnames=character(nr+nsmr-1)
 Cnames=character(nc+nsmc-1)
 Rnames=rep(sep,nr+nsmr-1)
 Cnames=rep(sep,nc+nsmc-1)
 for(i in 1:nsmr ){
  Rnames[rr[i,1]:rr[i,2] + i-1]=rnames[rr[i,1]:rr[i,2]]
  for( j in 1:nsmc ){
   # Print(i,j,rr[i,1]:rr[i,2] + i-1,rc[j,1]:rc[j,2] + (j-1))
   # Print(getSM(smatf,i,j))
   M[rr[i,1]:rr[i,2] + i-1,rc[j,1]:rc[j,2] + (j-1)]=
    smatf[rr[i,1]:rr[i,2],rc[j,1]:rc[j,2], drop=0]
  }
 }
 for( j in 1:nsmc )
  Cnames[rc[j,1]:rc[j,2] + j-1]=cnames[rc[j,1]:rc[j,2]]
 
 # Print(Rnames,Cnames,dim(M))
 rownames(M)=Rnames
 colnames(M)=Cnames
 
 cat(name,"\n")
 print(M, quote=0)
 
 return( invisible(smat) )
 
} # end of Printb




#' 
#' @rdname Printb
#' @export
#' 

printb <- Printb

# end of printb



