# These functions make the w, F, x and g matrices
#
#
# Author: srazbash
###############################################################################

makeTBATSFMatrix <- function(
  alpha,
  beta = NULL,
  small.phi = NULL,
  seasonal.periods = NULL,
  k.vector = NULL,
  gamma.bold.matrix = NULL,
  ar.coefs = NULL,
  ma.coefs = NULL
) {
  # 1. Alpha Row
  F <- matrix(1, nrow = 1, ncol = 1)
  if (!is.null(beta)) {
    F <- cbind(F, matrix(small.phi, nrow = 1, ncol = 1))
  }
  if (!is.null(seasonal.periods)) {
    tau <- sum(k.vector) * 2
    zero.tau <- matrix(0, nrow = 1, ncol = tau)
    F <- cbind(F, zero.tau)
  }
  if (!is.null(ar.coefs)) {
    p <- length(ar.coefs)
    ar.coefs <- matrix(ar.coefs, nrow = 1, ncol = p)
    alpha.phi <- alpha * ar.coefs
    F <- cbind(F, alpha.phi)
  }
  if (!is.null(ma.coefs)) {
    q <- length(ma.coefs)
    ma.coefs <- matrix(ma.coefs, nrow = 1, ncol = q)
    alpha.theta <- alpha * ma.coefs
    F <- cbind(F, alpha.theta)
  }

  # 2. Beta Row
  if (!is.null(beta)) {
    beta.row <- matrix(c(0, small.phi), nrow = 1, ncol = 2)
    if (!is.null(seasonal.periods)) {
      beta.row <- cbind(beta.row, zero.tau)
    }
    if (!is.null(ar.coefs)) {
      beta.phi <- beta * ar.coefs
      beta.row <- cbind(beta.row, beta.phi)
    }
    if (!is.null(ma.coefs)) {
      beta.theta <- beta * ma.coefs
      beta.row <- cbind(beta.row, beta.theta)
    }
    F <- rbind(F, beta.row)
  }

  # 3. Seasonal Row
  if (!is.null(seasonal.periods)) {
    seasonal.row <- t(zero.tau)
    if (!is.null(beta)) {
      seasonal.row <- cbind(seasonal.row, seasonal.row)
    }

    # Make the A matrix
    A <- matrix(0, tau, tau)
    last.pos <- 0
    for (i in seq_along(k.vector)) {
      if (seasonal.periods[i] != 2) {
        C <- makeCIMatrix(
          k = as.integer(k.vector[i]),
          m = as.double(seasonal.periods[i])
        )
      } else {
        C <- matrix(0, 1, 1)
      }
      S <- makeSIMatrix(
        k = as.integer(k.vector[i]),
        m = as.double(seasonal.periods[i])
      )

      # C <- matrix(0,k.vector[i],k.vector[i])
      # for(j in seq_len(k.vector[i])) {
      # 	l <- round((2*pi*j/seasonal.periods[i]), digits=15)
      # 	C[j,j] <- cos(l)
      # }
      # S <- matrix(0,k.vector[i],k.vector[i])
      # for(j in seq_len(k.vector[i])) {
      # 	S[j,j] <- sin(2*pi*j/seasonal.periods[i])
      # }
      # print(C)
      # print(S)
      Ai <- makeAIMatrix(
        C = C,
        S = S,
        k = as.integer(k.vector[i])
      )
      A[
        (last.pos + 1):(last.pos + (2 * k.vector[i])),
        (last.pos + 1):(last.pos + (2 * k.vector[i]))
      ] <- Ai
      last.pos <- last.pos + (2 * k.vector[i])
    }
    seasonal.row <- cbind(seasonal.row, A)

    if (!is.null(ar.coefs)) {
      B <- t(gamma.bold.matrix) %*% ar.coefs
      seasonal.row <- cbind(seasonal.row, B)
    }
    if (!is.null(ma.coefs)) {
      C <- t(gamma.bold.matrix) %*% ma.coefs
      seasonal.row <- cbind(seasonal.row, C)
    }
    F <- rbind(F, seasonal.row)
  }

  # 4. AR() Rows
  if (!is.null(ar.coefs)) {
    # p <- length(ar.coefs)
    ar.rows <- matrix(0, nrow = p, ncol = 1)
    if (!is.null(beta)) {
      ar.rows <- cbind(ar.rows, ar.rows)
    }
    if (!is.null(seasonal.periods)) {
      ar.seasonal.zeros <- matrix(0, nrow = p, ncol = tau)
      ar.rows <- cbind(ar.rows, ar.seasonal.zeros)
    }
    ident <- diag((p - 1))
    ident <- cbind(ident, matrix(0, nrow = (p - 1), ncol = 1))
    ar.part <- rbind(ar.coefs, ident)
    ar.rows <- cbind(ar.rows, ar.part)

    if (!is.null(ma.coefs)) {
      ma.in.ar <- matrix(0, nrow = p, ncol = q)
      ma.in.ar[1, ] <- ma.coefs
      ar.rows <- cbind(ar.rows, ma.in.ar)
    }

    F <- rbind(F, ar.rows)
  }

  # 5. MA() Rows
  if (!is.null(ma.coefs)) {
    ma.rows <- matrix(0, nrow = q, ncol = 1)
    if (!is.null(beta)) {
      ma.rows <- cbind(ma.rows, ma.rows)
    }
    if (!is.null(seasonal.periods)) {
      ma.seasonal <- matrix(0, nrow = q, ncol = tau)
      ma.rows <- cbind(ma.rows, ma.seasonal)
    }
    if (!is.null(ar.coefs)) {
      ar.in.ma <- matrix(0, nrow = q, ncol = p)
      ma.rows <- cbind(ma.rows, ar.in.ma)
    }
    ident <- diag((q - 1))
    ident <- cbind(ident, matrix(0, nrow = (q - 1), ncol = 1))
    ma.part <- rbind(matrix(0, nrow = 1, ncol = q), ident)
    ma.rows <- cbind(ma.rows, ma.part)
    F <- rbind(F, ma.rows)
  }
  F
}

# makeWMatrix <- function(small.phi=NULL, seasonal.periods=NULL, ar.coefs=NULL, ma.coefs=NULL) {
#
# 	the.list <- makeBATSWMatrix(smallPhi = small.phi, sPeriods = as.integer(seasonal.periods), arCoefs = ar.coefs, maCoefs = ma.coefs)
#
#
# 	return(the.list)
#
# }

# makeGMatrix <- function(alpha, beta=NULL, gamma.vector=NULL, seasonal.periods=NULL, p=0, q=0) {
# 	li <- makeBATSGMatrix(alpha, beta, gamma.vector, as.integer(seasonal.periods), as.integer(p), as.integer(q))
#
# 	return(li)
# }

makeFMatrix <- function(
  alpha,
  beta = NULL,
  small.phi = NULL,
  seasonal.periods = NULL,
  gamma.bold.matrix = NULL,
  ar.coefs = NULL,
  ma.coefs = NULL
) {
  # 1. Alpha Row
  F <- matrix(1, nrow = 1, ncol = 1)
  if (!is.null(beta)) {
    F <- cbind(F, matrix(small.phi, nrow = 1, ncol = 1))
  }
  if (!is.null(seasonal.periods)) {
    tau <- sum(seasonal.periods)
    zero.tau <- matrix(0, nrow = 1, ncol = tau)
    F <- cbind(F, zero.tau)
  }
  if (!is.null(ar.coefs)) {
    p <- length(ar.coefs)
    ar.coefs <- matrix(ar.coefs, nrow = 1, ncol = p)
    alpha.phi <- alpha * ar.coefs
    F <- cbind(F, alpha.phi)
  }
  if (!is.null(ma.coefs)) {
    q <- length(ma.coefs)
    ma.coefs <- matrix(ma.coefs, nrow = 1, ncol = q)
    alpha.theta <- alpha * ma.coefs
    F <- cbind(F, alpha.theta)
  }

  # 2. Beta Row
  if (!is.null(beta)) {
    beta.row <- matrix(c(0, small.phi), nrow = 1, ncol = 2)
    if (!is.null(seasonal.periods)) {
      beta.row <- cbind(beta.row, zero.tau)
    }
    if (!is.null(ar.coefs)) {
      beta.phi <- beta * ar.coefs
      beta.row <- cbind(beta.row, beta.phi)
    }
    if (!is.null(ma.coefs)) {
      beta.theta <- beta * ma.coefs
      beta.row <- cbind(beta.row, beta.theta)
    }
    F <- rbind(F, beta.row)
  }

  # 3. Seasonal Row
  if (!is.null(seasonal.periods)) {
    seasonal.row <- t(zero.tau)
    if (!is.null(beta)) {
      seasonal.row <- cbind(seasonal.row, seasonal.row)
    }

    # Make the A matrix
    for (i in seasonal.periods) {
      if (i == seasonal.periods[1]) {
        a.row.one <- matrix(0, nrow = 1, ncol = i)
        a.row.one[i] <- 1
        a.row.two <- cbind(diag((i - 1)), matrix(0, nrow = (i - 1), ncol = 1))
        A <- rbind(a.row.one, a.row.two)
      } else {
        old.A.rows <- dim(A)[1]
        old.A.columns <- dim(A)[2]
        a.row.one <- matrix(0, nrow = 1, ncol = i)
        a.row.one[i] <- 1
        a.row.two <- cbind(diag((i - 1)), matrix(0, nrow = (i - 1), ncol = 1))
        Ai <- rbind(a.row.one, a.row.two)
        A <- rbind(A, matrix(0, nrow = dim(Ai)[1], ncol = old.A.columns))
        A <- cbind(A, matrix(0, nrow = dim(A)[1], ncol = dim(Ai)[2]))
        A[
          ((old.A.rows + 1):(old.A.rows + dim(Ai)[1])),
          ((old.A.columns + 1):(old.A.columns + dim(Ai)[2]))
        ] <- Ai
      }
    }
    seasonal.row <- cbind(seasonal.row, A)

    if (!is.null(ar.coefs)) {
      B <- t(gamma.bold.matrix) %*% ar.coefs
      seasonal.row <- cbind(seasonal.row, B)
    }
    if (!is.null(ma.coefs)) {
      C <- t(gamma.bold.matrix) %*% ma.coefs
      seasonal.row <- cbind(seasonal.row, C)
    }
    F <- rbind(F, seasonal.row)
  }

  # 4. AR() Rows
  if (!is.null(ar.coefs)) {
    # p <- length(ar.coefs)
    ar.rows <- matrix(0, nrow = p, ncol = 1)
    if (!is.null(beta)) {
      ar.rows <- cbind(ar.rows, ar.rows)
    }
    if (!is.null(seasonal.periods)) {
      ar.seasonal.zeros <- matrix(0, nrow = p, ncol = tau)
      ar.rows <- cbind(ar.rows, ar.seasonal.zeros)
    }
    ident <- diag((p - 1))
    ident <- cbind(ident, matrix(0, nrow = (p - 1), ncol = 1))
    ar.part <- rbind(ar.coefs, ident)
    ar.rows <- cbind(ar.rows, ar.part)

    if (!is.null(ma.coefs)) {
      ma.in.ar <- matrix(0, nrow = p, ncol = q)
      ma.in.ar[1, ] <- ma.coefs
      ar.rows <- cbind(ar.rows, ma.in.ar)
    }

    F <- rbind(F, ar.rows)
  }

  # 5. MA() Rows
  if (!is.null(ma.coefs)) {
    ma.rows <- matrix(0, nrow = q, ncol = 1)
    if (!is.null(beta)) {
      ma.rows <- cbind(ma.rows, ma.rows)
    }
    if (!is.null(seasonal.periods)) {
      ma.seasonal <- matrix(0, nrow = q, ncol = tau)
      ma.rows <- cbind(ma.rows, ma.seasonal)
    }
    if (!is.null(ar.coefs)) {
      ar.in.ma <- matrix(0, nrow = q, ncol = p)
      ma.rows <- cbind(ma.rows, ar.in.ma)
    }
    ident <- diag((q - 1))
    ident <- cbind(ident, matrix(0, nrow = (q - 1), ncol = 1))
    ma.part <- rbind(matrix(0, nrow = 1, ncol = q), ident)
    ma.rows <- cbind(ma.rows, ma.part)
    F <- rbind(F, ma.rows)
  }
  F
}

makeXMatrix <- function(
  l,
  b = NULL,
  s.vector = NULL,
  d.vector = NULL,
  epsilon.vector = NULL
) {
  x.transpose <- matrix(l, nrow = 1, ncol = 1)
  if (!is.null(b)) {
    x.transpose <- cbind(x.transpose, matrix(b, nrow = 1, ncol = 1))
  }
  if (!is.null(s.vector)) {
    x.transpose <- cbind(
      x.transpose,
      matrix(s.vector, nrow = 1, ncol = length(s.vector))
    )
  }

  if (!is.null(d.vector)) {
    x.transpose <- cbind(
      x.transpose,
      matrix(d.vector, nrow = 1, ncol = length(d.vector))
    )
  }

  if (!is.null(epsilon.vector)) {
    x.transpose <- cbind(
      x.transpose,
      matrix(epsilon.vector, nrow = 1, ncol = length(epsilon.vector))
    )
  }

  x <- t(x.transpose)
  list(x = x, x.transpose = x.transpose)
}
