#########################################
# times_functions.R	                #
# These functions set the time stamps   #
# using the internal BSC convention in  #
# the tall towers dataset               # 
# jramon - October 2017                 #
#########################################
library(lubridate)
#---------------------------
# This function transforms POSIXct time into amount of time (i.e. 'hours since')
# Function arguments:
# old.times: vector containing times in POSICxt format
# NOTE: This function has to be applied after checking that all time stamps are in the list 'time'
#--------------------------- 
utc2amount <- function(old.times)
{       #---------------------------
        # Time definition and attributes
        #--------------------------- 
        time 		<- list()
        time$units 	<- paste0("hours since ",as.Date(old.times[1])," 00:00:00")
        time$long_name 	<- paste0("hours since ",as.Date(old.times[1])," 00:00:00")

        #---------------------------
        # Transform UTC date into 'hours since'
	#---------------------------
	time$values <- utinvcal.nc(time$units, format(strptime(as.POSIXct(old.times, "%Y-%m-%d %H:%M:%S"), "%Y-%m-%d %H:%M:%S")))

	return(time)
}

#---------------------------
# This function transforms time values from 'start interval representing time' to 'middle interval representing time'
# Function arguments:
# amount.time: list containing a column named amount.time$values with the times in 'hours since'
#--------------------------- 
beginning2middle <- function(amount.time)
{	#---------------------------
        # Transform time values to the central interval time value
        #---------------------------
	amount.time$vals_2cols <- embed(amount.time$values,2)	
	amount.time$values <- rowMeans(amount.time$vals_2cols)

	#---------------------------
        # Set the last value
        #---------------------------
	amount.time$values[length(amount.time$values)+1] <- 2*amount.time$values[length(amount.time$values)]-amount.time$values[length(amount.time$values)-1]
	
        return(amount.time)
}

#---------------------------
# This function transforms time values from 'end interval representing time' to 'middle interval representing time'
# Function arguments:
# amount.time: list containing a column named amount.time$values with the times in 'hours since'
#--------------------------- 
end2middle <- function(amount.time)
{	#---------------------------
        # Transform time values to the central interval time value
        #---------------------------
        amount.time$vals_2cols <- embed(amount.time$values,2)
        amount.time$vals     <- rowMeans(amount.time$vals_2cols)

        #---------------------------
        # Define first value and build the new time vector
	# Conditional to avoid negative time (no temporal sense) values
        #---------------------------
        if (amount.time$values[1] != 0) {
		first.element <- 2*amount.time$vals[1] - amount.time$vals[2]
		amount.time$values <- c(first.element,amount.time$vals)
	}
	
	else {
		first.element <- 0
		amount.time$values <- c(first.element,amount.time$vals)
	}

        return(amount.time)
}

#----------------------------------------
# Ensure that all the time stamps are represented in the dataset
# obs.dt: a data.table (or data.table) containing values for a specific month
# required a column named "times" obs.dt$times, with "POSIXct" "POSIXt" class 	
# frequencies: minutely/10minutely/hourly/30secondly/20minutely/6minutely/30minutely/15minutely
# opt: Whether time stamp is set to HH:00 (opt=1), HH:30 (opt=2), HH:05 (opt=3)
# monthly: if TRUE, fill all time stamps for the specified month (yyyymm).
#	   if FALSE, fill all time stamps for the specified period anyi, anyf
#----------------------------------------
check_times <- function(obs.dt,freq,yyyymm,opt=1,monthly=TRUE,anyf=NULL) {
	#---------------------------
        # Remove rows with duplicated time stamps
        #---------------------------
        obs.dt <- obs.dt[!duplicated(obs.dt$times),]
	
	#-------------------------------------
	# Identify data sampling
	#-------------------------------------
	if (freq == "minutely") { 
		sampl = minutes(1) 
		str.sampl = "1 min"
	} 
	else if (freq == "30secondly") { 
		sampl = seconds(30)
		str.sampl = "30 sec"
	}
	else if (freq == "10minutely") { 
		sampl = minutes(10)
		str.sampl = "10 min"
	}
	else if (freq == "hourly") {
		sampl = hours(1)
		str.sampl = "1 hour"
	}
	else if (freq == "20minutely") {
		sampl = minutes(20)
		str.sampl = "20 min"
	}
	else if (freq == "6minutely") {
		sampl = minutes(6)
		str.sampl = "6 min"
	}
	else if (freq == "30minutely") {
		sampl = minutes(30)
		str.sampl = "30 min"
	}
	else if (freq == "15minutely") {
                sampl = minutes(15)
                str.sampl = "15 min"
        }
	else if (freq == "5minutely") {
		sampl = minutes(5)
		str.sampl = "5 min"
	}
	
	else {
		stop(paste0("Unrecognized frequency: ",freq))
	}
	
	#-------------------------------------
	# Set limits of the theoretical time interval
	#-------------------------------------
	if (opt == 1) {
		first_day <- ymd_hm(paste0(yyyymm,"01_0000"))
	}
	
	# In this case, we are given hourly data with middle interval time stamp convention
	else if (opt == 2) {
		first_day <- ymd_hm(paste0(yyyymm,"01_0030"))
	}
	
	# In this case, we are given 10-minutely data with middle interval time stamp convention
	else if (opt == 3) {
		first_day <- ymd_hm(paste0(yyyymm,"01_0005"))
	}			
	
	if(monthly) { last_day <- first_day + months(1) - sampl }
	else { last_day <- first_day + years(anyf-year(ymd(paste0(yyyymm,'01')))+1) - sampl }
	
	#-------------------------------------
	# Create theoretical time sequence
	#-------------------------------------
	tmp.df <- list()
	tmp.df$times <- seq(first_day,last_day,str.sampl) 

	#-------------------------------------
	# Merge the 2 data frames
	# Need to specify that it is used the 'base' package
	#-------------------------------------	
	obs.dt <- base::merge(obs.dt,tmp.df,by.x ="times",by.y="times", all.y=T)

	return(obs.dt)
}

#---------------------------
# This function transforms a character frequency (defined as time stamp sampling) into seconds
# Function arguments:
#   frequency: char vector specifying the time stamp sampling of the data
#--------------------------- 
freq2sec <- function(freq) {
	
	if (freq == "minutely") {freq.in.sec = 60}
        
        else if (freq == "30secondly") {freq.in.sec = 30}
              
        else if (freq == "10minutely") {freq.in.sec = 600}
                
        else if (freq == "hourly") {freq.in.sec = 3600}
                
        else if (freq == "20minutely") {freq.in.sec = 1200}
                
        else if (freq == "6minutely") {freq.in.sec = 360}
                
        else if (freq == "30minutely") {freq.in.sec = 1800}
             
        else if (freq == "15minutely") {freq.in.sec = 900}
        
	else if (freq == "5minutely") {freq.in.sec = 300}        
        
	else {
                stop(paste0("Unrecognized frequency: ",freq),". You can add it into times_functions.R file within the function freq2sec")
        }
	
	return(freq.in.sec)
}

#---------------------------
# This function transforms a frequency in minutes (defined as time stamp sampling) into string
# Function arguments:
#   frequency: numeric vector specifying the time stamp sampling of the data
#--------------------------- 
freq2string <- function(freq.in.min) {

        if (freq.in.min == 60) {freq = "hourly"}

        else if (freq.in.min == 0.5) {freq = "30secondly"}

        else if (freq.in.min == 10) {freq = "10minutely"}

        else if (freq.in.min == 20) {freq = "20minutely"}

        else if (freq.in.min == 6) {freq = "6minutely"}

        else if (freq.in.min == 30) {freq = "30minutely"}

        else if (freq.in.min == 15) {freq = "15minutely"}

        else if (freq.in.min == 5) {freq = "5minutely"}

        else {
                stop(paste0("Unrecognized frequency: ",freq),". 
                                You can add it into times_functions.R file within the function freq2sec")
        }

        return(freq)
}

#----------------------------------------
# Define plotting features depending on the length of the considered time period
# times: vector containing time stamps in POSIXct
# gral.var: windagl, wdiragl, taagl
# rmarkdown: If we pretend to create a summary pdf of the data, turn on rmarkdown option
#----------------------------------------
plotting_features <- function(times,gral.var,rmarkdown=0) {
	#-------------------------------------
        # Coerce times into POSIXct format 
        #-------------------------------------
	times <- as.POSIXct(times)
	
	#-------------------------------------
        # Extremes of time intervals 
        #-------------------------------------
        feat <- list()
	feat$max <- times[length(times)]
        feat$min <- times[1]
	
	#-------------------------------------
        # Axis labels depending on the length of time series.
        # If the time series is between 8 and 16 years, annual labels
        # if it is more than 16 year, 5-annual labels
        #-------------------------------------
        por.in.days <- as.numeric(feat$max - feat$min)
        if (por.in.days <= 15) {
        	feat$time_label <- "%d %b %Y %H:%M"
                feat$interv_date <- "2 day"
        	feat$point.size <- 1.2
		feat$alpha <- 1 # opaque
	}

        else if (por.in.days > 15 & por.in.days <= 31) {
        	feat$time_label <- "%d %b %Y"
                feat$interv_date <- "4 day"
		feat$point.size <- 1
		feat$alpha <- 1 # opaque
	}
	

        else if (por.in.days > 31 & por.in.days <= 90) {
        	feat$time_label <- "%d %b %Y"
                feat$interv_date <- "10 day"
		feat$point.size <- 1
		feat$alpha <- 1 # opaque
	}

        else if (por.in.days > 90 & por.in.days <= 180) {
        	feat$time_label <- "%d %b %Y"
                feat$interv_date <- "20 day"
		feat$point.size <- 1
		feat$alpha <- 1 # opaque
	}
			
	# Between 6 months and 1 year
	else if (por.in.days > 180 & por.in.days <= 365) {
        	feat$time_label <- "%b %Y"
                feat$interv_date <- "1 month"
		feat$point.size <- 1
		feat$alpha <- 1 # opaque
	}

	# Between 1 and 5 years
        else if (por.in.days > 365 & por.in.days <= 1825) {
        	feat$time_label <- "%b %Y"
                feat$interv_date <- "6 month"
		feat$point.size <- 0.7
		feat$alpha <- 1 # opaque
	}
	
	# Between 5 and and 16 years
        else if (por.in.days > 1825 & por.in.days < 5840) {
        	feat$time_label <- "%Y"
                feat$interv_date <- "1 year"
		feat$point.size <- 0.1
		feat$alpha <- 0 # transparent
	}

	# Between 16 and 24 years
        else if (por.in.days >= 5840 & por.in.days < 8760)  {
        	feat$time_label <- "%Y"
                feat$interv_date <- "2 year"
		feat$point.size <- 0.00002
		feat$alpha <- 0 # transparent
	}

	# More than 24 years
        else if (por.in.days >= 8760) {
        	feat$time_label <- "%Y"
                feat$interv_date <- "5 year"
		feat$point.size <- 0.00002
		feat$alpha <- 0 # transparent
	}

	if (gral.var == "taagl") {
		feat$point.color = "black"
	}
	
	else {
		feat$point.color = "blue"	
	}
		
	if (rmarkdown == 1) {
		feat$point.size <- 0.000002
		feat$ncol <- 2
	}
	
	else {
		feat$ncol <- 1
	}	

	return(feat)
}
