#' Interprete sas-like abbreviated variable list
#'
#' @param var string containing sas-like abbreviated variable list such as\cr
#'              "q5-q7  x1  height--gender"\cr
#'         Comma can be a denominator.
#' @param varlistf full list of variables on the basis of which double - is
#' interpreted. \cr
#' Use varlistf=colnames(data)\cr
#' This can be NULL when double - is not used.
#' @param location = 1 to output the locatin of var in varlistf \cr
#'  If location == 1, varlistf must be given.
#' @param regexpr a string containing a regular expression to be used
#' to select the variables. \cr
#' This has priority over var.
#'
#' @return vector or list
#' @details
#' varlist( "q2-q5 a c--d", varlistf=c("a", "bb","c","d", "e", "gender") ) \cr
#' will return c( "q2", "q3", "q4", "q5", "a",  "c",  "d" )\cr
#'   When location == 1, in addition to the vector above, \cr
#'    the location of the variable names contained in varlistf, if any,
#'    will be output as the 2nd element of the list, which is\cr
#'    c(1,3,4)
#'    \cr
#'   Expression such as abc: can be used to designate all the variables
#'   whose names start with abc.
#'
#' @examples
#' varlist( "x3-x1, y5, x8-x9" )
#' varlistf=c("a", "b","c","d", "e", paste("Q", 1:5, sep=""), "fff" )
#' varlist( "q2-q5 a e--c", varlistf=varlistf )
#' varlist( "q2-q5 a e--c Q:", varlistf=varlistf )
#' varlist( regexpr="^Q[123]", varlistf=varlistf )
#'
#' @export
#'

varlist <- function( var=NULL, varlistf=NULL, location=0, regexpr=NULL ){
 # interprete sas-like abbreviated variable list
 # Shin-ichi Mayekawa
 # 20140527,28
 # check if var is a string: 20170920
 # root:: 20180419dnc,20
 # regexpr: 20180420
 # && -> &: 20190605,1230cot
 #
 #
 # Args:
 #
 #   var       string containing sas-like abbreviated variable list such as
 #              "q5-q7  x1  height--gender"
 #             comma can be a denominator.
 #   varlistf  full list of variables on the basis of which -- is interpreted
 #              varlistf=colnames(data)
 #
 #   location = 1 to output the locatin of var in varlistf
 #             If location == 1, varlistf must be given.
 #
 # Values:
 #
 #   When location == 0, this function outputs
 #    the expanded variable list as a vector as
 #       c("q5","q6","x1","height",....,"gender")
 #   When location == 1, in addition to the vector above,
 #    the location of each variable in var will be output as the 2nd element
 #    of the list.
 #

 if( !is.null(var) ){
  # is var a string
  if( !( is.vector(var)  &  typeof(var) == "character" ) ){
   cat("\n\nerror1:(varlist) var must be a string of length one.\n")
   stop()
  }
  # error
  if( any(regexpr("--",var) > 0)  && is.null(varlistf) ){
   cat("\n\nerror1:(varlist) \n"
       , " When you specify --, you must specify varlistf=.\n" )
   return(NULL)
  }
 }

 if( !is.null(regexpr)  && is.null(varlistf) ){
  cat("\n\nerror1:(varlist) \n"
      , " When you specify regexpr, you must specify varlistf=.\n" )
  return(NULL)
 }


 # Is regexpr given?
 if( !is.null(regexpr) ){
  # regexpr given

  varlist=varlistf[ grep( regexpr, varlistf ) ]

 }
 else{
  # regexpr is not given.

  vl=unlist( strsplit( var, "[, ]") )
  vl=vl[which(vl != "")]
  lenvl=length(vl)

  # Print(lenvl,vl)

  varlist=NULL
  for( i in 1:lenvl ){

   if( regexpr("--",vl[i]) > 0 ){

    if( regexpr(":",vl[i]) > 0 ){
     cat("\n\nerror1:(varlist)  -- and : cannot be mixed.\n")
     return(NULL)
    }

    #Print("--",i,vl[i],varlistf)
    var=unlist(strsplit(vl[i],"--"))
    if( length(var) < 2 ){
     cat("\n\nerror1:(varlist)   Must have two variable names.\n")
     return(NULL)
    }
    loc=which(varlistf %in% var)
    #Print(loc)
    if( length(loc) < 2 ){
     cat("\n\nerror1:(varlist)   Invalid variable name.\n")
     return(NULL)
    }
    if( var[1] == varlistf[loc[1]] )
     vari=varlistf[loc[1]:loc[2]]
    else
     vari=varlistf[loc[2]:loc[1]]

   }
   else if( regexpr(":",vl[i]) > 0 ){

    if( regexpr("--",vl[i]) > 0 ){
     cat("\n\nerror1:(varlist)  -- and : cannot be mixed.\n")
     return(NULL)
    }

    #Print(":",i,vl[i],varlistf)
    root=unlist(strsplit(vl[i],":"))
    if( length(root) >= 2 | root == "" ){
     cat("\n\nerror1:(varlist)   root: please.\n")
     return(NULL)
    }
    loc=grep(root, varlistf)
    loc=which(regexpr(root,varlistf)>0)
    # Print(root,loc)
    vari=varlistf[loc]

   }
   else if( regexpr("-",vl[i]) > 0 ){

    roots=unlist(strsplit(vl[i],"[[:digit:]-]"))
    roots=roots[which(roots != "")]
    #Print(roots)
    if( is.na(roots[2]) ){
     cat("\n\nerror1:(varlist)  Must have the same alpha roots",
         " on the both sides of --.\n")
     return(NULL)
    }
    if( roots[1] != roots[2] ){
     cat(
      "\n\nerror1:(varlist)"
      , "Must have the same alpha roots on the both sides"
      , " of -.\n")
     return(NULL)
    }
    #Print(i,vl[i],roots)
    num=unlist(strsplit(vl[i],paste("[",roots[1],"-]",collapse="")))
    num=num[which(num!="")]
    #Print(num)
    vari=paste(roots[1],num[1]:num[2],sep="")
    #Print(vari)

   }
   else{
    vari=vl[i]
   }
   varlist=c(varlist,vari)

  } # end of i loop

 }

 # location in varlistf
 if( location > 0 ){
  if( is.null(varlistf) ){
   cat("\n\nerror1:(varlist) When location=1 varlistf must be given.\n^n")
   return(NULL)
  }
  loc=loceq(varlistf,varlist)
  res=list(varlist=varlist, loc=loc)
 }
 else res=varlist

 return( res )

} # end of varlist


