#' 
#' @title Finalizes the output of the function \code{table2d.ds}
#' @description This is an INTERNAL i.e. it is not 'exported' and hence not visible to users.
#' This function is only called by the client function \code{ds.table2d}. It calls other 
#' internal functions namely \code{table2dhelper1}, \code{table2dhelper2} and \code{table2dhelper3}.
#' @param server.func.output a list object returned by the server side function \code{table2d.ds}
#' @param var.name.1 a character string, the name of the first input numerical vector
#' @param var.name.2 a character string, the name of the second input numerical vector
#' @return a list that contains the elements returned by the client function \code{ds.table2d}
#' @author Burton, P.; Gaye, A.
#'
table2dhelper4 <- function(server.func.output, var.name.1, var.name.2){                           
         
  # in the whole script the key elements required to produce the final key outputs are highlighted between dashed line 
  # after the call to the helper function that produced them. The key elements not generated by the helper functions 
  # are directly obtained or derived from the arguments of the current function. Some key elements are required only if
  # there is at least one valid study.
  
  #--------------------------------------------------#                      
  opals.names <- names(server.func.output)
  #--------------------------------------------------# 
  
   
  # call the 1st helper script to carry out validity checks on the tables returned by the 'table2d.ds'
  helper1out <- dsbaseclient:::table2dhelper1(server.func.output, var.name.1, var.name.2) 
  #--------------------------------------------------#
  num.valid.tables <- helper1out$num.valid.tables                      
  opals.valid.binary <- helper1out$opals.valid.binary
  opals.valid.id <- helper1out$opals.valid.id
  zero.studies.valid <- helper1out$zero.studies.valid
  #--------------------------------------------------# 
  
                          
  # call the 2nd helper script to generate the 'valid.output.array'
  arg1 <- server.func.output
  arg2 <- helper1out$num.valid.tables
  arg3 <- helper1out$opals.valid.binary
  arg4 <- helper1out$opals.valid.id
  arg5 <- helper1out$zero.studies.valid
  helper2out <- dsbaseclient:::table2dhelper2(arg1, arg2, arg3, arg4, arg5)
  #------------------------------------------------------#                      
  valid.output.array <- helper2out$valid.output.array
  num.cats.1 <- helper2out$num.cats.1
  num.cats.2 <- helper2out$num.cats.2   
  unique.categories.1 <- helper2out$unique.categories.1  
  unique.categories.2  <- helper2out$unique.categories.2
  #------------------------------------------------------# 
  
  
  # call the 3rd helper script to generate the percents from the counts
  arg1 <- server.func.output
  arg2 <- helper2out$valid.output.array
  arg3 <- helper1out$zero.studies.valid
  arg4 <- helper2out$unique.categories.1
  arg5 <- helper2out$unique.categories.2
  arg6 <- helper2out$num.cats.1
  arg7 <- helper2out$num.cats.2
  arg8 <- helper1out$opals.valid.id
  arg9 <- helper1out$num.valid.tables
  helper3out <-dsbaseclient:::table2dhelper3(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9)       
  #------------------------------------------------------#
  final.output.list <- helper3out$final.output.list
  valid.counts.array <- helper3out$valid.counts.array
  valid.rowperc.array <- helper3out$valid.rowperc.array   
  valid.colperc.array <- helper3out$valid.colperc.array 
  valid.globalperc.array  <- helper3out$valid.globalperc.array   
  #------------------------------------------------------# 


  # only enact if at least one study is valid
  if(zero.studies.valid==FALSE){ 
      
    invalid.study.output.obj <- NULL
    for(k in 1:length(opals.valid.binary))
    {
      if(opals.valid.binary[k]==0) {invalid.study.output.obj <- c(invalid.study.output.obj,k)}
    }
    
    # create flags if all studies are valid or not
    if(is.null(invalid.study.output.obj))study.validity.flag <- "ALL STUDIES VALID"
    if(!is.null(invalid.study.output.obj))study.validity.flag <- paste("DATA INVALID IN AT LEAST ONE STUDY, SEE TOP OF OUTPUT -> STUDY",
                                                                       invalid.study.output.obj," - ",opals.names[invalid.study.output.obj])
    
    valid.tables.by.study.array <- array(NA,dim=c((num.cats.1+1),(num.cats.2+1),4,(num.valid.tables+1)))
    dimnames(valid.tables.by.study.array) <- list(c(unique.categories.1,"TOTAL"),c(unique.categories.2,"TOTAL"),
                                        c(c(paste("COUNTS",var.name.1,"(rows) V ",var.name.2,"(cols)")),
                                          c(paste("COLUMN.PERCENTS",var.name.1,"(rows) V ",var.name.2,"(cols)")),
                                          c(paste("ROW.PERCENTS",var.name.1,"(rows) V ",var.name.2,"(cols)")),
                                          c(paste("GLOBAL.PERCENTS",var.name.1,"(rows) V ",var.name.2,"(cols)"))
                                         ),c(opals.names[opals.valid.id],"ALL VALID STUDIES COMBINED"))

    for(p in 1:(num.valid.tables+1))
    {
      valid.tables.by.study.array[,,1,p] <- valid.counts.array[,,p]
      valid.tables.by.study.array[,,2,p] <- valid.colperc.array[,,p]
      valid.tables.by.study.array[,,3,p] <- valid.rowperc.array[,,p]
      valid.tables.by.study.array[,,4,p] <- valid.globalperc.array[,,p]    
    }

    # chisquare calculations 
    chi2.matrix <- matrix(NA,nrow=(num.valid.tables+1),ncol=3)
    dimnames(chi2.matrix) <- list(c(opals.names[opals.valid.id],"ALL VALID STUDIES COMBINED"),c("X2-value","df","p-value")) 
    for(q in 1:(num.valid.tables+1))    
    {
      table.temp <- valid.counts.array[,,q]
      dd1 <- dim(table.temp)[1]
      dd2 <- dim(table.temp)[2]
      table.for.chi2 <- table.temp[(1:(dd1-1)),(1:(dd2-1))]
      chi2 <- chisq.test(table.for.chi2)
      chi2.matrix[q,1] <- chi2$statistic
      chi2.matrix[q,2] <- chi2$parameter
      chi2.matrix[q,3] <- chi2$p.value     
    }
    
    # output if at least one study is valid
    terminal.output.list <- list(final.output.list,as.array(valid.counts.array),as.array(valid.colperc.array),
                                 as.array(valid.rowperc.array),as.array(valid.globalperc.array),as.array(valid.tables.by.study.array),
                                 as.matrix(chi2.matrix),study.validity.flag)
      
    names(terminal.output.list)[[1]] <- "OPALS.DATA.OVERVIEW"    
    names(terminal.output.list)[[2]] <- "TABLES.VALID.DATA.COUNTS"    
    names(terminal.output.list)[[3]] <- "TABLES.VALID.DATA.COLUMN.PERCENTS"    
    names(terminal.output.list)[[4]] <- "TABLES.VALID.DATA.ROW.PERCENTS"    
    names(terminal.output.list)[[5]] <- "TABLES.VALID.DATA.GLOBAL.PERCENTS"    
    names(terminal.output.list)[[6]] <- "ALL.VALID.TABLES.BY.STUDY"    
    names(terminal.output.list)[[7]] <- "CHI2.TESTS.FOR.HOMOGENEITY"    
    names(terminal.output.list)[[8]] <- "VALIDITY.WARNING"  
  } 
  
  if(zero.studies.valid==TRUE)
  { 
    # output if no study is valid
    study.validity.flag <- "NO STUDIES HAVE VALID DATA - SO NO ATTEMPT TO COMBINE"
    terminal.output.list <- list(final.output.list,study.validity.flag)
    names(terminal.output.list)[[1]] <- "OPALS.DATA.OVERVIEW"
    names(terminal.output.list)[[2]] <- "VALIDITY.WARNING"
  } 
  
  return(terminal.output.list)
} 

