#' @export

loglikBIRT=function(object,marginal=TRUE,nquad=15,silent=FALSE){
  mcmc=object$mcmc
  model=object$model
  inflated=object$inflated
  N=nrow(object$z)
  nit=ncol(object$z)
  item.out=object$output
  z=as.matrix(object$z)
  z[z==-999]=NA
  alpha=rstan::extract(mcmc,"alpha")$"alpha"
  nsamples0=nrow(alpha)
  nsamples=nsamples0
  index=rev(seq(nsamples0,nsamples0-nsamples,by=-1))
  alpha=alpha[index,]
  beta=rstan::extract(mcmc,"beta")$"beta"[index,]
  phi=rstan::extract(mcmc,"phi")$"phi"[index,]
  if(model=="beta") ln_phi=log(phi)
  if(model=="simplex"){
    dsimplex=function (y, m, s2){  #from rmutil by Swihart & Lindsey (2022) but with minor adjustment
      tmp <- -((y - m)/(m * (1 - m)))^2/(2 * y * (1 - y) * s2) -
        (log(2 * pi * s2) + 3 * (log(y) + log(1 - y)))/2
      return(exp(tmp))
    }
  }
  theta=rstan::extract(mcmc,"theta")$"theta"[index,]


  if(inflated=="zero" | inflated=="both") gamma0_c=rstan::extract(mcmc,"gamma0")$"gamma0"[index,] else gamma0_c=matrix(-Inf,nsamples,nit)
  if(inflated=="one" | inflated=="both") gamma1_c=rstan::extract(mcmc,"gamma1")$"gamma1"[index,] else gamma1_c=matrix(Inf,nsamples,nit)


  if(inflated=="zero" | inflated=="both"){
    if(inflated=="zero"){
      one_mask=rep(0,nit)
      one_mask_matrix=diag(0,nit)
    }
    zero_mask=1*(is.finite(item.out[,"gamma0"]))
    zero_mask_matrix=matrix(0,sum(zero_mask),nit)
    for(i in 1:nit){
      if(zero_mask[i]==1) zero_mask_matrix[sum(zero_mask[1:i]),i]=1
      if(zero_mask[i]==0) zero_mask_matrix[sum(zero_mask[1:i]),i]=0
    }
  }

  if(inflated=="one" | inflated=="both"){
    if(inflated=="one"){
      zero_mask=rep(0,nit)
      zero_mask_matrix=diag(0,nit)
    }
    one_mask=1*(is.finite(item.out[,"gamma1"]))
    one_mask_matrix=matrix(0,sum(one_mask),nit)
    for(i in 1:nit){
      if(one_mask[i]==1) one_mask_matrix[sum(one_mask[1:i]),i]=1
      if(one_mask[i]==0) one_mask_matrix[sum(one_mask[1:i]),i]=0
    }
  }

  gamma0=gamma0_c%*%zero_mask_matrix
  gamma0[,zero_mask==0]=-Inf
  gamma1=gamma1_c%*%one_mask_matrix
  gamma1[,one_mask==0]=Inf

  if(!marginal){
    log_lik=array(,dim = c(nsamples,N,nit))
    a=b=rep(0,nit)
    out=rep(NA,nit)
    for(s in 1:nsamples){
      if(!silent) cat("Calculating conditional log_lik for posterior sample: ",s,"\r")
      for(p in 1:N){
          ind=(z[p,]!=0) & (z[p,]!=1) & (!is.na(z[p,]))
          ind0=(z[p,]==0) & (!is.na(z[p,]))
          ind1=(z[p,]==1) & (!is.na(z[p,]))
          prob01=stats::plogis(gamma1[s,ind]-alpha[s,ind]*theta[s,p]) - stats::plogis(gamma0[s,ind]-alpha[s,ind]*theta[s,p])

          if(model=="beta"){
              a[ind] = exp(.5* (alpha[s,ind]*theta[s,p] + beta[s,ind]+ln_phi[s,ind]));
              b[ind]  = exp(.5* (-alpha[s,ind]*theta[s,p] - beta[s,ind]+ln_phi[s,ind]));
              out[ind]= prob01*stats::dbeta(z[p,ind],a[ind],b[ind])
          }
          if(model=="simplex")
            out[ind] = prob01*dsimplex(z[p,ind],stats::plogis(beta[s,ind]+alpha[s,ind]*theta[s,p]),phi[s,ind])

          if(model=="samejima")
            out[ind]= prob01*1/(z[p,ind]*(1-z[p,ind]))*stats::dnorm(stats::qlogis(z[p,ind]),beta[s,ind]+alpha[s,ind]*theta[s,p],sqrt(phi[s,ind]))

          if(model=="normal")
            out[ind]= prob01*stats::dnorm(z[p,ind],beta[s,ind]+alpha[s,ind]*theta[s,p],sqrt(phi[s,ind]))

          out[ind0]=stats::plogis(gamma0[s,ind0]-alpha[s,ind0]*theta[s,p])
          out[ind1]=1-stats::plogis(gamma1[s,ind1]-alpha[s,ind1]*theta[s,p])
          log_lik[s,p,]=log(out)

      }
    }
  log_lik=apply(log_lik,c(1,2),sum)
  }
  if(marginal){
    Quad=statmod::gauss.quad(nquad,kind="hermite")
    W=Quad$weights/sqrt(pi)
    A=Quad$nodes*sqrt(2)

    log_lik=matrix(,nsamples,N)
    a=b=rep(0,nit)
    out=rep(NA,nit)
    for(s in 1:nsamples){
      if(!silent) cat("Calculating marginal log_lik for posterior sample: ",s,"\r")
      for(p in 1:N){
        tmp=0
        for(k in 1:nquad){
          ind=(z[p,]!=0) & (z[p,]!=1) & (!is.na(z[p,]))
          ind0=(z[p,]==0) & (!is.na(z[p,]))
          ind1=(z[p,]==1) & (!is.na(z[p,]))
          prob01=stats::plogis(gamma1[s,ind]-alpha[s,ind]*A[k]) - stats::plogis(gamma0[s,ind]-alpha[s,ind]*A[k])

          if(model=="beta"){
            a[ind] = exp(.5* (alpha[s,ind]*A[k] + beta[s,ind]+ln_phi[s,ind]));
            b[ind]  = exp(.5* (-alpha[s,ind]*A[k] - beta[s,ind]+ln_phi[s,ind]));
            out[ind]= prob01*stats::dbeta(z[p,ind],a[ind],b[ind])
          }
          if(model=="simplex")
            out[ind] = prob01*dsimplex(z[p,ind],stats::plogis(beta[s,ind]+alpha[s,ind]*A[k]),phi[s,ind])

          if(model=="samejima")
            out[ind]= prob01*1/(z[p,ind]*(1-z[p,ind]))*stats::dnorm(stats::qlogis(z[p,ind]),beta[s,ind]+alpha[s,ind]*A[k],sqrt(phi[s,ind]))

          if(model=="normal")
            out[ind]= prob01*stats::dnorm(z[p,ind],beta[s,ind]+alpha[s,ind]*A[k],sqrt(phi[s,ind]))

          out[ind0]=stats::plogis(gamma0[s,ind0]-alpha[s,ind0]*A[k])
          out[ind1]=1-stats::plogis(gamma1[s,ind1]-alpha[s,ind1]*A[k])
          tmp=tmp+W[k]*prod(out,na.rm=TRUE)
        }
        log_lik[s,p]=log(tmp)
      }
    }
  }
  if(!silent) cat("\n")
  return(log_lik)
}
