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

import com.airlock.iam.common.domain.model.token.oathotp.HotpToken;
import com.airlock.iam.common.domain.model.token.oathotp.OathOtpToken;
import com.airlock.iam.common.domain.model.token.oathotp.TotpToken;
import com.airlock.iam.core.misc.util.oathotp.OathOtpUtilities;
import com.airlock.iam.core.misc.util.qrcode.QrCodeUtilities;
import com.google.common.base.Preconditions;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.awt.image.BufferedImage;
import java.net.URI;
import java.util.Optional;

public final class OathOtpTokenQrCodeView {
   public static final OathOtpTokenQrCodeView DEFAULT_VIEW = new OathOtpTokenQrCodeView(300, 300);
   private final int width;
   private final int height;

   private OathOtpTokenQrCodeView(int width, int height) {
      this.width = width;
      this.height = height;
   }

   public static OathOtpTokenQrCodeView defaultView() {
      return DEFAULT_VIEW;
   }

   public BufferedImage qrCodeOf(TotpToken totpToken) {
      return this.qrCodeOf(totpToken, Optional.empty());
   }

   public BufferedImage qrCodeOf(HotpToken hotpToken) {
      return this.qrCodeOf(hotpToken, Optional.of(hotpToken.getEventCounter()));
   }

   public URI dataUriOf(TotpToken totpToken) {
      return QrCodeUtilities.createPngDataUriFromImage(this.qrCodeOf(totpToken));
   }

   public URI dataUriOf(HotpToken hotpToken) {
      return QrCodeUtilities.createPngDataUriFromImage(this.qrCodeOf(hotpToken));
   }

   private BufferedImage qrCodeOf(OathOtpToken token, Optional<Long> counter) {
      return QrCodeUtilities.createQrCodeImage(this.createQrCodeUrlFromToken(token, counter), this.width, this.height);
   }

   private String createQrCodeUrlFromToken(OathOtpToken token, Optional<Long> counter) {
      Preconditions.checkNotNull(token);
      Preconditions.checkArgument(token.getSecretBase32().isPresent());
      return OathOtpUtilities.constructOathOtpQrUrl(token.getUserId(), token.getOrganizationLabel(), (String)token.getSecretBase32().get(), counter);
   }

   @SuppressFBWarnings(justification = "generated code")
   public int getWidth() {
      return this.width;
   }

   @SuppressFBWarnings(justification = "generated code")
   public int getHeight() {
      return this.height;
   }

   @SuppressFBWarnings(justification = "generated code")
   @Override
   public boolean equals(Object o) {
      if (o == this) {
         return true;
      } else if (!(o instanceof OathOtpTokenQrCodeView other)) {
         return false;
      } else {
         return this.width != other.width ? false : this.height == other.height;
      }
   }

   @SuppressFBWarnings(justification = "generated code")
   @Override
   public int hashCode() {
      int PRIME = 59;
      int result = 1;
      result = result * 59 + this.width;
      return result * 59 + this.height;
   }

   @SuppressFBWarnings(justification = "generated code")
   @Override
   public String toString() {
      return "OathOtpTokenQrCodeView(width=" + this.getWidth() + ", height=" + this.getHeight() + ")";
   }
}
