package com.criticalblue.reactnative;

import okhttp3.*;

import java.io.IOException;
import java.security.cert.Certificate;
import java.util.HashMap;
import java.util.List;

import android.util.Log;

public class LoggingInterceptor implements Interceptor {
  private CertificatePinner certificatePinner;
  private HashMap<String, DomainProperty> domainPropertyHashMap = new HashMap<>();

  public LoggingInterceptor(CertificatePinner certificatePinner, List<DomainProperty> domainProperties) {
    this.certificatePinner = certificatePinner;
    for (DomainProperty domainProperty : domainProperties) {
      for (String pin : domainProperty.getPins()) {
        domainPropertyHashMap.put(pin, domainProperty);
      }
    }
  }

  @Override
  public Response intercept(Interceptor.Chain chain) throws IOException {
    Log.v("ADInterceptor", "Intercepting");
    String host = chain.request().url().host();
    Connection connection = chain.connection();
    Handshake handshake = connection != null ? connection.handshake() : null;
    List<Certificate> certs = handshake != null ? handshake.peerCertificates() : null;

    try {
      certificatePinner.check(host, certs);
      Log.d("ADInterceptor", "Passed validation - HOST: " + host);
      return chain.proceed(chain.request());
    } catch (Exception e) {
      Log.v("ADInterceptor", "Failed validation - HOST: " + host + ", " + e.getMessage());
      List<CertificatePinner.Pin> pins = certificatePinner.findMatchingPins(host);
      CertificatePinner.Pin pin = pins.isEmpty() ? null : pins.get(0);
      String pinString = pin == null ? null : pin.toString();
      if (pinString == null
              || domainPropertyHashMap.get(pinString) == null
              || domainPropertyHashMap.get(pinString).isEnforcePinning()) {
        Log.v("ADInterceptor", "Pinning is enabled for this host. Connection aborted.");
        throw new IOException();
      }
      Log.v("ADInterceptor", "Pinning is disabled for this PIN: " + pinString);
      return chain.proceed(chain.request());
    }
  }
}