### export.fwf.R
###------------------------------------------------------------------------------------------
### What: script to export dataset to fixed width format file & data dictionary json file
### Time-stamp: <2017-11-23 11:21:27 assyst>
###-------------------------------------------------------------------------------------------

## Input Parameters
# data file path (csv)
csvpath <- input[[1]]
# variable details (json)
jsonpath <- input[[2]]
# filepath of output file
outpath <- input[[3]]
# libary path (R library path embedded in MDE)
libPath <- input[[4]]
# directory to load functions
workingDirectory <- input[[5]]
#TAKE LOCALE AS INPUT
lcl <- input[[6]]

# Set working directory
setwd(workingDirectory);

# Load functions
source("fn.write.fwf.R")
source("fn.stata.type.R")
source("fn.variable.width.R")
source("fn.common.utilities.R")

# load packages
load.packages(c('haven', 'jsonlite', 'readr'), libPath)

# set initial configurations like memory limit, locale
set.configurations(lcl=lcl)

# Read JSON 
flattenData <- fromJSON(jsonpath)

# read data file
DF_DATA <- read.datafile(flattenData, file=csvpath)

# Calculate width, start column and end column
startCol <- 0
endCol <- 0

for (i in 1:nrow(flattenData)){
  
  variable.name <- flattenData$internalName[[i]]
  
  # Get category values
  category.values <- flattenData$val[[i]]
  
  # no. of decimal positions
  dcml <- flattenData$dcml[[i]]

  if( flattenData$type[[i]] == "numeric"){
    # to handle the scenario where dcml greater than the length of the variable
    # for ex: value =  1, dcml = 2, then value will be converted to 1.00'
     DF_DATA[[variable.name]] <- format.num(DF_DATA[[variable.name]], dcml=dcml)
  }

  # calculate variable length
  length <- varibale.width(DF_DATA[[variable.name]], flattenData$type[[i]], category.values)  
  
  #length <- nchar(maxValue)
  startCol <- endCol +1
  endCol <- endCol + length
  
  # Update JSON
  flattenData$width[[i]] <- length
  flattenData$StartPos[[i]] <- startCol
  flattenData$EndPos[[i]] <- endCol
  
  # Update storage type & read format
  
  if(flattenData$type[[i]] == "character"){
    
    # storage type "str<length>""
    # stata read format "%<length>s"
    flattenData$StorageType[[i]] <- paste("str", length, sep="") 
    flattenData$ReadFormat[[i]] <- paste("%", length, "s", sep="")
    
  } else if( flattenData$type[[i]] == "numeric" ){    
    
    # stata read format "%<length>.<decimal>s"
    
    flattenData$StorageType[[i]] <- stata.datatype(DF_DATA[[variable.name]])
    if(dcml == 0){
      flattenData$ReadFormat[[i]] <- paste("%", length, "f", sep="")
    } else {
      flattenData$ReadFormat[[i]] <- paste("%", length, ".", dcml, "f", sep="")
    }
    
    
  } else if(flattenData$type[[i]] == "date") {
    
    # date read format & storage type
    flattenData$StorageType[[i]] <- "date"
    flattenData$ReadFormat[[i]] <- "%td"
    
  } else {
    # get type & read format from variable info
    flattenData$StorageType[[i]] <- vapply(DF_DATA[[variable.name]], typeof, character(1))[[1]]
    flattenData$ReadFormat[[i]] <- paste( "%", length, "." , dcml, "g", sep="")
  } 
  
}

# write fixed width format file
columnNames <- as.character(unlist(flattenData$internalName))
columnWidths <- as.numeric(unlist(flattenData$width))
columnRound <- c(rep(0,length(flattenData$name)))

# select columns from data frame to make sure the column order and to remove deleted variables
DF_DATA <- data.frame(DF_DATA[, columnNames])

## write fixed width file with options 
# width     - column width
# colnames  - exclude header row
# sep       - delemeter
write.fwf(DF_DATA,locale=lcl, encoding = "UTF-8", file = outpath, width = columnWidths, na="*", colnames = FALSE, sep = "")


# Update JSON doc with the updated sequence. It will be used while generating the dictionary file
varjson <- toJSON(flattenData,pretty=TRUE,force=TRUE)


# reset the locale to english to resolve the write json issues
reset.locale(lcl)
  
write(encode.UTF(varjson), jsonpath)

return(0)


