require(reshape2)

# x - old -    cols.mets  <- c( "Impressions", "Soc.Impressions", "Clicks", "Soc.Clicks", "CTR", "CPC", "CPM", "Spend", "Freq", "Actions", "uClicks", "uCTR",  "uCPM", "Reach", 
# x - old -      "Soc.Reach", "uCPC", "PeopleActioning", "Likes.Page", "Engagement.Page", "Engagement.Post", "Likes.Post", "Comments.Post", "Shares.post", "Views.PagePhoto", "Views.VideoPlays", "Clicks.Link", "Conversion.Website", "Conversion.OtherWebsite", "Mentions.Page", "EventResponse")
# x - old -    cols.demog <- c("Age", "Gender") 
# x - old -    cols.info.main  <- c("Date", "CampaignID", "AdID") 
# x - old -    cols.info.extra <- c("Year", "Campaign",   "Ad")
# x - old -    cols.info <- sort(c(cols.info.main, cols.info.extra))


## Wrapper function for aggregating THIS data.table
aggBy <- function(byCols, DateIn=FALSE, DateOut=FALSE, verbose=TRUE) {
# if DateIn,  will add "Date" to the front of `byCols` if not already present
# if DateOut, will remove "Date" from `byCols` if present.
# If both are FALSE will leave byCols as they are. 

  if (DateOut && DateIn)
    stop("Cannot have *both* DateIn & DateOut be TRUE. Pick one.")

  if (DateIn && !("Date" %in% byCols)) 
    byCols <- c("Date", byCols)
  if (DateOut) 
    byCols <- setdiff(byCols, "Date")

  if (verbose)
    cat("Cols using are: ", paste("", byCols, sep="\n\t"), "\n")
  copy(fb[, lapply(.SD, sum), .SDcols=cols.mets, by=byCols])
}


## Aggregate by demographic
fb.agg.demog <- aggBy(cols.demog, DateIn=TRUE, verbose=FALSE)


### SIMPLE
cols.simple.info <- c("Date", "Age", "Gender")
cols.simple.mets <- c("Impressions", "Clicks", "Spend", "Actions")
cols.simple <- c(cols.simple.info, cols.simple.mets)
fb.agg.demog.simple <- fb.agg.demog[, cols.simple, with=FALSE]

## Aggregate each Demo col, other than Date
computeTotals <- function(DT, col.Total, byCols=NULL, col.mets=cols.simple.mets) {
  tt <- setNames(as.list(rep("TOTAL", length(col.Total))), col.Total)
  setcolorderpt(
     DT[, c(lapply(.SD, sum), tt), .SDcols=col.mets, by=byCols]
   , intersect(names(DT), c(byCols, col.Total, col.mets))
  )
}

## Add rows for total values, for cache'ing the aggregates
fb.agg.demog.simple <- 
  rbindFactorCheck(silent=TRUE, l=list(
        fb.agg.demog.simple, 
        computeTotals(fb.agg.demog.simple, "Age", by=c("Date", "Gender")), 
        computeTotals(fb.agg.demog.simple, "Gender", by=c("Date", "Age")),
        computeTotals(fb.agg.demog.simple, c("Age", "Gender"), by=c("Date"))
    ))



## ------------------------------------ ##
##  Calculate key metric summaries      ##
## ------------------------------------ ##
calc.CTR_(fb.agg.demog.simple)
calc.CPC_(fb.agg.demog.simple, Cost="Spend")
calc.CPM_(fb.agg.demog.simple, Cost="Spend")

calc.CTR_(fb.agg.demog.simple, Click="Actions", assignTo="ATR")
calc.CPC_(fb.agg.demog.simple, Cost="Spend", Click="Actions", assignTo="CPA")

# drop the individual metric columns
fb.agg.demog.simple[, c(cols.simple.mets) := NULL]
## ------------------------------------ ##

# make the demog columns into factors
fb.agg.demog.simple[, c("Age", "Gender") := list(factor(Age), factor(Gender))]
fb.agg.demog.simple[Age==""]


# reshape
## ------------------------------------ ##
  dat <- data.table( melt(fb.agg.demog.simple, id.vars=cols.simple.info)
              , key=c("Age", "Gender", "Date") )
## ------------------------------------ ##


## This gives the totals, by date
fb.Total <- dat[.("TOTAL", "TOTAL")]

## ## MANUAL CHECK THAT THE ABOVE GIVES THE CORRECT AGGR TOTALS
## manual <- fb.agg.demog[, list("CTR.manual"=sum(Clicks) * 100 / sum(Impressions)), by=Date]
## auto   <- dat[.("TOTAL", "TOTAL")][variable=="CTR"]
## setkey(manual, "Date")
## setkey(auto, "Date")
## # The manually calculated CTR.maual should be the same as the value from auto 
## stopifnot(  merge(manual, auto)[, all(CTR.manual == value)] )


## Backup your work 
saveImageTo()
