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

import com.airlock.iam.core.misc.persistency.token.TokenBean;
import java.util.Optional;
import org.apache.commons.lang3.StringUtils;

public class OAuth2TokenTableAccessToken extends AbstractTokenTableOAuth2Token implements OAuth2TokenWithHash, OAuth2AccessToken {
   protected static final String ACCESS_TOKEN_SUBTYPE = "access_token";

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

   public static OAuth2TokenTableAccessToken createOAuth2AccessToken(
      TokenBean delegate, RawOAuth2TokenWithHash rawAccessToken, SessionInfo sessionInfo, AccessTokenInfo accessTokenInfo, int expiresIn
   ) {
      OAuth2TokenTableAccessToken token = new OAuth2TokenTableAccessToken(delegate);
      token.initialize(OAuth2Token.OAuth2TokenType.ACCESS_TOKEN, rawAccessToken.getTokenKey(), sessionInfo, accessTokenInfo.scopes(), expiresIn);
      token.setHashedTokenSecret(rawAccessToken.getHash());
      accessTokenInfo.tokenBinding().ifPresent(token::setTokenBinding);
      return token;
   }

   public static OAuth2TokenTableAccessToken createOAuth2AccessToken(
      TokenBean delegate,
      RawOAuth2TokenWithHash rawAccessToken,
      SessionInfo sessionInfo,
      AccessTokenInfo accessTokenInfo,
      int expiresIn,
      RawOAuth2TokenWithHash refreshToken
   ) {
      OAuth2TokenTableAccessToken token = createOAuth2AccessToken(delegate, rawAccessToken, sessionInfo, accessTokenInfo, expiresIn);
      token.setRefreshTokenReference(refreshToken);
      return token;
   }

   @Override
   public String getHashedTokenSecret() {
      return this.getGenericDataElement2();
   }

   private void setHashedTokenSecret(String tokenSecretHash) {
      this.setGenericDataElement2(tokenSecretHash);
   }

   public Optional<LinkedTokenReference> getRefreshTokenReference() {
      String refreshTokenString = this.getGenericDataElement5();
      return StringUtils.isBlank(refreshTokenString) ? Optional.empty() : Optional.of(LinkedTokenReference.fromDbValue(refreshTokenString));
   }

   private void setRefreshTokenReference(RawOAuth2TokenWithHash refreshToken) {
      this.setGenericDataElement5(LinkedTokenReference.fromRawToken(refreshToken).toDbValue());
   }

   @Override
   public Optional<OAuth2TokenBinding> getTokenBinding() {
      return Optional.ofNullable(this.getGenericDataElement10()).filter(StringUtils::isNotBlank).map(OAuth2TokenBinding::fromString);
   }

   public void setTokenBinding(OAuth2TokenBinding tokenBinding) {
      this.setGenericDataElement10(tokenBinding.asString());
   }
}
