package com.airlock.iam.admin.domain.model.token.matrixcard;

import com.airlock.iam.base.api.domain.model.identity.Identity;
import com.airlock.iam.base.misc.date.LocalDateHelper;
import com.airlock.iam.core.misc.tanserver.core.HashedTokenList;
import com.airlock.iam.core.misc.tanserver.core.TokenHash;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.time.Duration;
import java.util.Arrays;
import java.util.Date;
import java.util.Objects;
import java.util.Optional;

public final class MatrixCardImpl implements MatrixCard {
   private final Optional<Duration> validityDuration;
   private final HashedTokenList tokenList;
   private final Identity<MatrixCard> identity;

   public MatrixCardImpl(HashedTokenList tokenList, Identity<MatrixCard> identity) {
      this.validityDuration = Optional.empty();
      this.tokenList = tokenList;
      this.identity = identity;
   }

   public Identity<MatrixCard> getId() {
      return this.identity;
   }

   @Override
   public Date getGeneratedAt() {
      return this.tokenList.getGenerationDate();
   }

   @Override
   public Optional<Date> getValidUntil() {
      return this.validityDuration.map(duration -> LocalDateHelper.toDate(LocalDateHelper.toLocalDateTime(this.getGeneratedAt()).plus(duration)));
   }

   @Override
   public int getNumberOfUnusedTokens() {
      return (int)Arrays.stream(this.getTokenHashes()).filter(Objects::nonNull).count();
   }

   @Override
   public int getTotalNumberOfTokens() {
      return this.getTokenHashes().length;
   }

   @Override
   public boolean hasId(Identity<MatrixCard> idToCompare) {
      return this.getId().equals(idToCompare);
   }

   public static MatrixCardImpl.MatrixCardImplBuilder builder(HashedTokenList tokenList, Identity<MatrixCard> identity) {
      return new MatrixCardImpl(tokenList, identity).toBuilder();
   }

   private TokenHash[] getTokenHashes() {
      TokenHash[] hashes = new TokenHash[this.tokenList.getNumberOfTokens()];

      for (int i = 0; i < hashes.length; i++) {
         hashes[i] = this.tokenList.getTokenHash(i);
      }

      return hashes;
   }

   @SuppressFBWarnings(justification = "generated code")
   public MatrixCardImpl.MatrixCardImplBuilder toBuilder() {
      return new MatrixCardImpl.MatrixCardImplBuilder().validityDuration(this.validityDuration).tokenList(this.tokenList).identity(this.identity);
   }

   @SuppressFBWarnings(justification = "generated code")
   public Optional<Duration> getValidityDuration() {
      return this.validityDuration;
   }

   @SuppressFBWarnings(justification = "generated code")
   public HashedTokenList getTokenList() {
      return this.tokenList;
   }

   @SuppressFBWarnings(justification = "generated code")
   public Identity<MatrixCard> getIdentity() {
      return this.identity;
   }

   @SuppressFBWarnings(justification = "generated code")
   @Override
   public boolean equals(Object o) {
      if (o == this) {
         return true;
      } else if (!(o instanceof MatrixCardImpl other)) {
         return false;
      } else {
         Object this$validityDuration = this.validityDuration;
         Object other$validityDuration = other.validityDuration;
         if (this$validityDuration == null ? other$validityDuration == null : this$validityDuration.equals(other$validityDuration)) {
            Object this$tokenList = this.tokenList;
            Object other$tokenList = other.tokenList;
            if (this$tokenList == null ? other$tokenList == null : this$tokenList.equals(other$tokenList)) {
               Object this$identity = this.identity;
               Object other$identity = other.identity;
               return this$identity == null ? other$identity == null : this$identity.equals(other$identity);
            } else {
               return false;
            }
         } else {
            return false;
         }
      }
   }

   @SuppressFBWarnings(justification = "generated code")
   @Override
   public int hashCode() {
      int PRIME = 59;
      int result = 1;
      Object $validityDuration = this.validityDuration;
      result = result * 59 + ($validityDuration == null ? 43 : $validityDuration.hashCode());
      Object $tokenList = this.tokenList;
      result = result * 59 + ($tokenList == null ? 43 : $tokenList.hashCode());
      Object $identity = this.identity;
      return result * 59 + ($identity == null ? 43 : $identity.hashCode());
   }

   @SuppressFBWarnings(justification = "generated code")
   @Override
   public String toString() {
      return "MatrixCardImpl(validityDuration=" + this.getValidityDuration() + ", tokenList=" + this.getTokenList() + ", identity=" + this.getIdentity() + ")";
   }

   @SuppressFBWarnings(justification = "generated code")
   public MatrixCardImpl(Optional<Duration> validityDuration, HashedTokenList tokenList, Identity<MatrixCard> identity) {
      this.validityDuration = validityDuration;
      this.tokenList = tokenList;
      this.identity = identity;
   }

   @SuppressFBWarnings(justification = "generated code")
   public static class MatrixCardImplBuilder {
      @SuppressFBWarnings(justification = "generated code")
      private Optional<Duration> validityDuration;
      @SuppressFBWarnings(justification = "generated code")
      private HashedTokenList tokenList;
      @SuppressFBWarnings(justification = "generated code")
      private Identity<MatrixCard> identity;

      @SuppressFBWarnings(justification = "generated code")
      MatrixCardImplBuilder() {
      }

      @SuppressFBWarnings(justification = "generated code")
      public MatrixCardImpl.MatrixCardImplBuilder validityDuration(Optional<Duration> validityDuration) {
         this.validityDuration = validityDuration;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public MatrixCardImpl.MatrixCardImplBuilder tokenList(HashedTokenList tokenList) {
         this.tokenList = tokenList;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public MatrixCardImpl.MatrixCardImplBuilder identity(Identity<MatrixCard> identity) {
         this.identity = identity;
         return this;
      }

      @SuppressFBWarnings(justification = "generated code")
      public MatrixCardImpl build() {
         return new MatrixCardImpl(this.validityDuration, this.tokenList, this.identity);
      }

      @SuppressFBWarnings(justification = "generated code")
      @Override
      public String toString() {
         return "MatrixCardImpl.MatrixCardImplBuilder(validityDuration="
            + this.validityDuration
            + ", tokenList="
            + this.tokenList
            + ", identity="
            + this.identity
            + ")";
      }
   }
}
