#' expand.grid with rev and colnames option
#'
#' @param ... vectors, factors or a list containing these.
#' @param rev = 1 to make the last elements of ... chage first.
#' @param colnames = 1 to use  ... as the column names.
#' @param KEEP.OUT.ATTRS
#'    a logical indicating the "out.attrs" attribute (see below) should be
#'    computed and returned.
#' @param stringsAsFactors
#'      logical specifying if character vectors are converted to factors.
#' @return A data frame.
#'
#' @details See comments of native expand.grid.\cr
#'   Compare \code{expand.grid( 1:2, 2:3 )} and
#'   \code{expand.grid1( 1:2, 2:3 )}.\cr
#'   \code{expand.grid1( 1:2, 2:3, rev=0 )} should be equal to
#'    native \code{expand.grid( 1:2, 2:3 )}. \cr
#'  \cr
#'  When the first element of ... is a list, expand.grid1 works
#'  as if it is called only with the first element.
#'  See the example below.\cr
#'
#'  \cr
#'  When ... contains a matrix, better use \code{cprod}.
#'
#' @examples
#'
#' Print( expand.grid( 1:2, 2:3 ), expand.grid1( 1:2, 2:3 ) )
#'
#' res=expand.grid( 1:2, c("a","b") )
#' res1=expand.grid1( 1:2, c("a","b") )
#' Print(res,res1)
#'
#'
#' ll=list(aaa=c("a","b"),bbb=1:3)
#' expand.grid1(ll, colnames=0)
#' expand.grid1(ll, colnames=1)
#' expand.grid1(ll, colnames=0, rev=0)
#' expand.grid1(ll, colnames=1, rev=0)
#'
#' expand.grid(ll,ll)
#' expand.grid1(ll,ll)
#'
#'
#' x=c("a","b"); y=1:3
#' expand.grid1(x,y, colnames=0)
#' expand.grid1(x,y, colnames=1)
#' expand.grid1(x,y, colnames=0, rev=0)
#' expand.grid1(x,y, colnames=1, rev=0)
#'
#'
#'
#' @export
#'

expand.grid1 <- function( ..., rev=1, colnames=0
                          , KEEP.OUT.ATTRS=TRUE, stringsAsFactors=FALSE  ){
 # expand.grid with rev option
 # Shin-ichi Mayekawa
 # 20140816
 # name: 20150609
 # list input: 20150730
 # analyze_three_dots: 20171127
 #
 # Same as the native expand.grid exept that
 #  when rev == 1, the last elements in ... changes first.
 #
 # Value:
 #
 #   data frame containing the resulting cartesian product of ... .
 #
 #   Character variables will remain as characters.
 #

 if( rev != 1 ){
  # rev != 1 : use native expand.grid
  res=expand.grid( ...
                   , KEEP.OUT.ATTRS=KEEP.OUT.ATTRS
                   , stringsAsFactors=stringsAsFactors )
  if( colnames == 0 ) return( res )
  else{
   resa=analyze_three_dots( ... )
   name=resa$name; val=resa$val
   if( is.list(val[[1]]) ){
    name=names(val[[1]])
   }
   colnames(res)=name
   return( res )
  }
 }
 else{
  # rev == 1
  resa=analyze_three_dots( ... )
  name=resa$name; val=resa$val

  # if the first of ... is a list, use the elements of it as the input.
  if( is.list(val[[1]]) ){
   name=names(val[[1]])
   val=val[[1]]
   #   names(val)=NULL
  }

  if( length(val) == 1 ){
   if( length(name) == 0 ){
    return( data.frame("Var1"=val[[1]]) )
   }
   else{
    res=data.frame(val)
    names(res[,1])=name
    return( res )
   }
  }

  vt=sapply(val,mode)
  res=t( apply(
   expand.grid( rev(val)
                , KEEP.OUT.ATTRS=KEEP.OUT.ATTRS
                , stringsAsFactors=stringsAsFactors )
   , 1, rev ) )

  if( colnames == 1 ) colnames(res)=name
  else colnames(res)=paste("Var",1:ncol(res),sep="")
  res=as.data.frame(res, stringsAsFactors=FALSE)
  for( j in 1:ncol(res) ) if( vt[j] == "numeric" ) res[,j]=as.numeric(res[,j])
  # res[,vt=="numeric"]=as.numeric(res[,vt=="numeric"])

  return( res )
 }

} # end of expand.grid1


