#'Computes the Trend of the Ensemble Mean
#'
#'Computes the trend along the forecast time of the ensemble mean by least 
#'square fitting, and the associated error interval.\cr
#'Trend() also provides the time series of the detrended ensemble mean 
#'forecasts.\cr
#'The confidence interval relies on a student-T distribution.\cr\cr
#'.Trend provides the same functionality but taking a matrix ensemble members 
#'as input (exp).
#'
#'@param var Array of any number of dimensions up to 10.
#'@param exp M by N matrix of M forecasts from N ensemble members.
#'@param interval Number of months/years between 2 points along posTR dimension.\cr
#'  Default = 1.\cr
#'  The trend would be provided in number of units per month or year.
#'@param siglev Confidence level for the computation of confidence interval.\cr
#'  Default = 0.95.
#'@param conf Whether to compute the confidence levels or not. Default = TRUE.
#'@param posTR Position along which to compute the trend.\cr
#'  Default = 2.
#'@param pldegree The degree/order of the polynomial to be fitted and removed
#'  (keep in mind that the degree must be smaller than the number of points 
#'  along posTR dimension). Default = 1 (linear fit) 
#'
#'@return 
#'\item{$trend}{
#'  Same dimensions as var except along posTR dimension which is replaced
#'  by a dimension:\cr
#'  \itemize{
#'    \item{conf = TRUE:\cr
#'          dimension length = 3 * (pldegree + 1)\cr
#'          Along the dimension shows: \cr
#'          a^(lo)_pldegree, a_pldegree, a^(hi)_pldegree,\cr
#'          a^(lo)_(pldegree-1), a_(pldegree-1), a^(hi)_(pldegree-1), ...\cr
#'          a_0 (intercept), a^(lo)_0, and a^(hi)_0, \cr
#'          where (lo)/(hi) is the lower/upper limit of the confidence interval
#'          for each point of the var along all other dimensions.
#'    }
#'    \item{conf = FALSE:\cr
#'          dimension length = pldegree + 3 \cr
#'       Along the dimension shows: \cr
#'          a_pldegree,\cr
#'          a_(pldegree-1), ...\cr
#'          a_0 (intercept), a^(lo)_0, and a^(hi)_0.
#'    }
#'  }
#'}
#'\item{$detrended}{
#'  Same dimensions as var with residual values (after removing polynomial
#'  fit of pldegree order) along the posTR dimension.
#'}
#'
#' Only in .Trend:
#'\item{$conf.int}{
#'  Corresponding to the limits of the \code{siglev}\% confidence interval 
#'  (only present if \code{conf = TRUE}) for the slope coefficient.
#'} 
#'
#'@keywords datagen
#'@author History:\cr
#'0.1  -  2011-05  (V. Guemas, \email{virginie.guemas@@ic3.cat})  -  Original code\cr
#'1.0  -  2013-09  (N. Manubens, \email{nicolau.manubens@@ic3.cat})  -  Formatting to CRAN\cr
#'2.0  -  2017-02  (A. Hunter, \email{alasdair.hunter@@bsc.es})  -  Adapt to veriApply()
#'2.8.6  -  2019-08  (A. Ho, \email{an.ho@bsc.es})  -  Adapt polynomial regression
#'
#'@examples
#'  # A test of the default linear fit:
#'  startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101')
#'  sampleData <- Load('tos', c('i00k'), c('ERSST'), startDates, nleadtime = 124, 
#'                     leadtimemin = 1, leadtimemax = 60, output = 'areave', 
#'                     latmin = 30, latmax = 45, lonmin = 0, lonmax = 40)
#'  months_between_startdates <- 60
#'  trend <- Trend(sampleData$obs, 3, months_between_startdates)
#'##PlotVsLTime(trend$trend, toptitle = "trend", ytitle = "K / (5 year)",
#'##            monini = 11, limits = c(-1,1), listexp = c('CMIP5 IC3'),
#'##            listobs = c('ERSST'), biglab = FALSE, hlines = 0,
#'##            fileout = 'tos_obs_trend.eps') -> there is an error in this step, but eps file is produced?
#'  PlotAno(trend$detrended, NULL, startDates, 
#'          toptitle = 'detrended anomalies (along the startdates)', ytitle = 'K',
#'          legends = 'ERSST', biglab = FALSE, fileout = 'tos_detrended_obs.eps') # there are warnings in this step!
#'  # A simple test of a nonlinear fit:
#'  y0 <- c(10.1, 8.8, 7.3, 4.12, -0.314, -5, -10.6, -18.2)
#'  y1 <- Trend(var=y0, posTR=1)               # linear fit
#'  y2 <- Trend(var=y0, posTR=1, pldegree=2)   # quadratic fit
#'  plot(y0)
#'  lines(y0 - y1$detrended, col='blue')       # linear fit
#'  lines(y0 - y2$detrended, col='red')        # quadratic fit
#'
#'@rdname Trend
#'@export
Trend_new <- function(var, posTR = 2, interval = 1, siglev = 0.95, conf = TRUE, pldegree = 1) {

#~~~~~~same
  # 
  #  Enlarge the size of var to 10 and move posTR to first position 
  # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  #  
  dimsvar <- dim(var)
  if (is.null(dimsvar)) { 
    dimsvar <- length(var) 
  }
  enlvar <- Enlarge(var, 10)
  outdim <- c(dimsvar, array(1, dim = (10 - length(dimsvar))))
#~~~~~~same



#--------------branch, should be removed
#  outdim[posTR] <- 3*(pldegree + 1)
#--------------branch, should be removed


#--------------master, should be kept
  if (conf) {
    nvals <- 3*(pldegree + 1)  #6, 9, 12, ...
#    poscoef2 <- 2
#    poscoef1 <- 4
  } else {
    nvals <- 3 + pldegree #4, 5, 6, ...
#    poscoef2 <- 1
#    poscoef1 <- 2
  }

  outdim[posTR] <- nvals
#--------------branch, should be kept



#~~~~~~same
  posaperm <- 1:10
  posaperm[posTR] <- 1
  posaperm[1] <- posTR
  enlvar <- aperm(enlvar, posaperm)
  dimsaperm <- outdim[posaperm]
#~~~~~~same

  if ( dim(enlvar)[1]<(pldegree + 1) ) { 
    stop("selected polynomial degree (pldegree) is too high")
  }

#~~~~~~same
  # 
  #  Loop on all dimensions to compute trends 
  # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # 
  enltrend <- array(dim = dimsaperm)
  enldetrend <- array(dim = dim(enlvar))
  for (j2 in 1:dimsaperm[2]) {
    for (j3 in 1:dimsaperm[3]) {
      for (j4 in 1:dimsaperm[4]) {
        for (j5 in 1:dimsaperm[5]) {
          for (j6 in 1:dimsaperm[6]) {
            for (j7 in 1:dimsaperm[7]) {
              for (j8 in 1:dimsaperm[8]) {
                for (j9 in 1:dimsaperm[9]) {
                  for (j10 in 1:dimsaperm[10]) {
                    tmp <- enlvar[, j2, j3, j4, j5, j6, j7, j8, j9, j10]
                    if (any(!is.na(tmp))) {
                      mon <- seq(tmp) * interval
#~~~~~~same


#----------------branch, should be kept
                      lm.out <- lm(tmp ~ poly(mon, degree=pldegree, raw=TRUE), na.action = na.omit)

                    if (conf) {
                      for (jj in (pldegree + 1):1) {
                        jj1 <- 1 + (pldegree + 1) - jj
                        if (jj==1) {   #last, deg = 0
                          enltrend[3*jj1 - 2, j2, j3, j4, j5, j6, j7, j8, j9, j10] <- lm.out$coefficients[jj]
                          enltrend[3*jj1 - 1, j2, j3, j4, j5, j6, j7, j8, j9, j10] <- confint(lm.out)[jj, 1]
                          enltrend[3*jj1,     j2, j3, j4, j5, j6, j7, j8, j9, j10] <- confint(lm.out)[jj, 2]
                        } else {
                          enltrend[3*jj1 - 2, j2, j3, j4, j5, j6, j7, j8, j9, j10] <- confint(lm.out)[jj, 1]
                          enltrend[3*jj1 - 1, j2, j3, j4, j5, j6, j7, j8, j9, j10] <- lm.out$coefficients[jj]
                          enltrend[3*jj1,     j2, j3, j4, j5, j6, j7, j8, j9, j10] <- confint(lm.out)[jj, 2]
                        }
                      }
                    } else {   #conf = FALSE
                      for (jj in (pldegree + 1):1) {
                        jj1 <- 1 + (pldegree + 1) - jj
                        if (jj==1) {
                          enltrend[jj1,     j2, j3, j4, j5, j6, j7, j8, j9, j10] <- lm.out$coefficients[jj]
                          enltrend[jj1 + 1, j2, j3, j4, j5, j6, j7, j8, j9, j10] <- confint(lm.out)[jj, 1]
                          enltrend[jj1 + 2, j2, j3, j4, j5, j6, j7, j8, j9, j10] <- confint(lm.out)[jj, 2]
                        } else {
                          enltrend[jj1,     j2, j3, j4, j5, j6, j7, j8, j9, j10] <- lm.out$coefficients[jj]
                        }
                      }

                    }


#----------------branch, should be kept


#-----------------same, should be deleted
#                      enldetrend[is.na(tmp) == FALSE, j2, j3, j4, j5, j6, j7, j8, j9, j10] <- tmp[is.na(tmp) == FALSE] - lm.out$fitted.values


#---------master, should be deleted
#                      lm.out <- lm(tmp ~ mon, na.action = na.omit)

#-----------------master, should be removed
#                      enltrend[poscoef2, j2, j3, j4, j5, j6, j7, j8, j9, 
#                               j10] <- lm.out$coefficients[2]
#                      enltrend[poscoef1, j2, j3, j4, j5, j6, j7, j8, j9, 
#                               j10] <- lm.out$coefficients[1]
#----------------master, should be removed

#----------------master, should be removed??????
#                      if (conf) {
#                        enltrend[c(1, 3), j2, j3, j4, j5, j6, j7, j8, j9, 
#                                 j10] <- confint(lm.out, level = siglev)[2, 1:2]
#                      }
#----------------master, should be ???????

#-----------------same
                      enldetrend[is.na(tmp) == FALSE, j2, j3, j4, j5, j6, j7, j8, j9, j10] <- tmp[is.na(tmp) == FALSE] - lm.out$fitted.values



                    }
                  } 
                }
              }
            }
          }
        }
      }
    }
  }
  # 
  #  Back to the original dimensions
  # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  #
#-----------master, should be kept
  enldetrend <- aperm(enldetrend, posaperm)
  dim(enldetrend) <- dimsvar 
  enltrend <- aperm(enltrend, posaperm)
### nvals >> 3*(pldegree + 1)
  dimsvar[posTR] <- nvals
  dim(enltrend) <- dimsvar

#-----------master, should be kept



  # 
  #  Outputs
  # ~~~~~~~~~
  # 



#<<<<<<< HEAD
#  detrended[] <- aperm(enldetrend, posaperm)
#  detrended <- array(dim = dimsvar)
#  trend[] <- aperm(enltrend, posaperm)
#  dimsvar[posTR] <- 3*(pldegree + 1)
#  trend <- array(dim = dimsvar)
#=======



  invisible(list(trend = enltrend, detrended = enldetrend))
}

#'@rdname Trend
#'@importFrom stats lm na.omit confint
#'@export
.Trend <- function(exp, interval = 1, siglev = 0.95, conf = TRUE) {
  
  ensmean <- rowMeans(exp, na.rm = TRUE)
  
  if (any(!is.na(ensmean))) {
    mon <- seq(ensmean) * interval
    lm.out <- lm(ensmean ~ mon, na.action = na.omit)
    trend <- c(lm.out$coefficients[2], lm.out$coefficients[1])
    if (conf) {
      conf.int <- confint(lm.out, level = siglev)[2, 1:2]
    }
    detrend <- ensmean[is.na(ensmean) == FALSE] - lm.out$fitted.values
  }  
                 
  # 
  #  Outputs
  # ~~~~~~~~~
  # 
  invisible(list(trend = trend, conf.int = conf.int, detrended = detrend))
}
