package com.airlock.iam.oauth2.domain.model.token;

import com.airlock.iam.base.api.domain.model.exception.ViolationException;
import com.airlock.iam.core.misc.persistency.token.TokenBean;
import com.airlock.iam.oauth2.domain.model.acr.OpenIdConnectAcrValue;
import com.airlock.iam.oauth2.domain.model.oidc.OidcUserAgentSessionId;
import java.util.Optional;

public class OpenIDConnectTokenTableIDToken extends AbstractTokenTableOAuth2Token implements OpenIDConnectIDToken {
   protected static final String ID_TOKEN_SUBTYPE = "id_token";

   public static OpenIDConnectTokenTableIDToken asTokenTableBasedOpenIDConnectIDToken(OAuth2Token token) {
      if (token instanceof OpenIDConnectTokenTableIDToken t) {
         return t;
      } else {
         throw new ViolationException("Cannot cast " + token.getClass().getSimpleName() + " to " + OpenIDConnectTokenTableIDToken.class.getSimpleName());
      }
   }

   public OpenIDConnectTokenTableIDToken(TokenBean delegate) {
      super(delegate);
   }

   public static OpenIDConnectTokenTableIDToken createOpenIDConnectIDToken(
      TokenBean delegate, OAuth2TokenKey idTokenKey, IdTokenInfo idTokenInfo, SessionInfo session, int expiresIn
   ) {
      OpenIDConnectTokenTableIDToken token = new OpenIDConnectTokenTableIDToken(delegate);
      token.initialize(OAuth2Token.OAuth2TokenType.OPENID_CONNECT_ID_TOKEN, idTokenKey, session, idTokenInfo.scopes(), expiresIn);
      idTokenInfo.nonce().ifPresent(token::setNonce);
      idTokenInfo.acr().ifPresent(token::setAcr);
      idTokenInfo.userAgentSessionId().ifPresent(token::setOidcUserAgentSessionId);
      return token;
   }

   @Override
   public Optional<String> getNonce() {
      return Optional.ofNullable(this.getGenericDataElement2());
   }

   private void setNonce(String nonce) {
      this.setGenericDataElement2(nonce);
   }

   @Override
   public Optional<OpenIdConnectAcrValue> getAcr() {
      return Optional.ofNullable(this.getGenericDataElement4()).map(OpenIdConnectAcrValue::of);
   }

   private void setAcr(OpenIdConnectAcrValue acr) {
      this.setGenericDataElement4(acr.name());
   }

   @Override
   public Optional<OidcUserAgentSessionId> getOidcUserAgentSessionId() {
      return Optional.ofNullable(this.getGenericDataElement10()).map(OidcUserAgentSessionId::new);
   }

   private void setOidcUserAgentSessionId(OidcUserAgentSessionId oidcUserAgentSessionId) {
      this.setGenericDataElement10(oidcUserAgentSessionId.id());
   }
}
