/* eslint-disable */
import {
  DistinguishedName,
  HashAlgorithm,
  hashAlgorithmFromJSON,
  hashAlgorithmToJSON,
  LogId,
  PublicKey,
  TimeRange,
  X509CertificateChain,
} from "./sigstore_common";

/**
 * TransparencyLogInstance describes the immutable parameters from a
 * transparency log.
 * See https://www.rfc-editor.org/rfc/rfc9162.html#name-log-parameters
 * for more details.
 * The included parameters are the minimal set required to identify a log,
 * and verify an inclusion proof/promise.
 */
export interface TransparencyLogInstance {
  /** The base URL at which can be used to URLs for the client. */
  baseUrl: string;
  /** The hash algorithm used for the Merkle Tree. */
  hashAlgorithm: HashAlgorithm;
  /**
   * The public key used to verify signatures generated by the log.
   * This attribute contains the signature algorithm used by the log.
   */
  publicKey:
    | PublicKey
    | undefined;
  /** The unique identifier for this transparency log. */
  logId: LogId | undefined;
}

/**
 * CertificateAuthority enlists the information required to identify which
 * CA to use and perform signature verification.
 */
export interface CertificateAuthority {
  /**
   * The root certificate MUST be self-signed, and so the subject and
   * issuer are the same.
   */
  subject:
    | DistinguishedName
    | undefined;
  /** The URI at which the CA can be accessed. */
  uri: string;
  /** The certificate chain for this CA. */
  certChain:
    | X509CertificateChain
    | undefined;
  /**
   * The time the *entire* chain was valid. This is at max the
   * longest interval when *all* certificates in the chain were valid,
   * but it MAY be shorter. Clients MUST check timestamps against *both*
   * the `valid_for` time range *and* the entire certificate chain.
   *
   * The TimeRange should be considered valid *inclusive* of the
   * endpoints.
   */
  validFor: TimeRange | undefined;
}

/**
 * TrustedRoot describes the client's complete set of trusted entities.
 * How the TrustedRoot is populated is not specified, but can be a
 * combination of many sources such as TUF repositories, files on disk etc.
 *
 * The TrustedRoot is not meant to be used for any artifact verification, only
 * to capture the complete/global set of trusted verification materials.
 * When verifying an artifact, based on the artifact and policies, a selection
 * of keys/authorities are expected to be extracted and provided to the
 * verification function. This way the set of keys/authorities can be kept to
 * a minimal set by the policy to gain better control over what signatures
 * that are allowed.
 *
 * The embedded transparency logs, CT logs, CAs and TSAs MUST include any
 * previously used instance -- otherwise signatures made in the past cannot
 * be verified.
 * The currently used instances MUST NOT have their 'end' timestamp set in
 * their 'valid_for' attribute for easy identification.
 * All the listed instances SHOULD be sorted by the 'valid_for' in ascending
 * order, that is, the oldest instance first and the current instance last.
 */
export interface TrustedRoot {
  /** MUST be application/vnd.dev.sigstore.trustedroot+json;version=0.1 */
  mediaType: string;
  /** A set of trusted Rekor servers. */
  tlogs: TransparencyLogInstance[];
  /**
   * A set of trusted certificate authorities (e.g Fulcio), and any
   * intermediate certificates they provide.
   * If a CA is issuing multiple intermediate certificate, each
   * combination shall be represented as separate chain. I.e, a single
   * root cert may appear in multiple chains but with different
   * intermediate and/or leaf certificates.
   * The certificates are intended to be used for verifying artifact
   * signatures.
   */
  certificateAuthorities: CertificateAuthority[];
  /** A set of trusted certificate transparency logs. */
  ctlogs: TransparencyLogInstance[];
  /** A set of trusted timestamping authorities. */
  timestampAuthorities: CertificateAuthority[];
}

function createBaseTransparencyLogInstance(): TransparencyLogInstance {
  return { baseUrl: "", hashAlgorithm: 0, publicKey: undefined, logId: undefined };
}

export const TransparencyLogInstance = {
  fromJSON(object: any): TransparencyLogInstance {
    return {
      baseUrl: isSet(object.baseUrl) ? String(object.baseUrl) : "",
      hashAlgorithm: isSet(object.hashAlgorithm) ? hashAlgorithmFromJSON(object.hashAlgorithm) : 0,
      publicKey: isSet(object.publicKey) ? PublicKey.fromJSON(object.publicKey) : undefined,
      logId: isSet(object.logId) ? LogId.fromJSON(object.logId) : undefined,
    };
  },

  toJSON(message: TransparencyLogInstance): unknown {
    const obj: any = {};
    message.baseUrl !== undefined && (obj.baseUrl = message.baseUrl);
    message.hashAlgorithm !== undefined && (obj.hashAlgorithm = hashAlgorithmToJSON(message.hashAlgorithm));
    message.publicKey !== undefined &&
      (obj.publicKey = message.publicKey ? PublicKey.toJSON(message.publicKey) : undefined);
    message.logId !== undefined && (obj.logId = message.logId ? LogId.toJSON(message.logId) : undefined);
    return obj;
  },
};

function createBaseCertificateAuthority(): CertificateAuthority {
  return { subject: undefined, uri: "", certChain: undefined, validFor: undefined };
}

export const CertificateAuthority = {
  fromJSON(object: any): CertificateAuthority {
    return {
      subject: isSet(object.subject) ? DistinguishedName.fromJSON(object.subject) : undefined,
      uri: isSet(object.uri) ? String(object.uri) : "",
      certChain: isSet(object.certChain) ? X509CertificateChain.fromJSON(object.certChain) : undefined,
      validFor: isSet(object.validFor) ? TimeRange.fromJSON(object.validFor) : undefined,
    };
  },

  toJSON(message: CertificateAuthority): unknown {
    const obj: any = {};
    message.subject !== undefined &&
      (obj.subject = message.subject ? DistinguishedName.toJSON(message.subject) : undefined);
    message.uri !== undefined && (obj.uri = message.uri);
    message.certChain !== undefined &&
      (obj.certChain = message.certChain ? X509CertificateChain.toJSON(message.certChain) : undefined);
    message.validFor !== undefined &&
      (obj.validFor = message.validFor ? TimeRange.toJSON(message.validFor) : undefined);
    return obj;
  },
};

function createBaseTrustedRoot(): TrustedRoot {
  return { mediaType: "", tlogs: [], certificateAuthorities: [], ctlogs: [], timestampAuthorities: [] };
}

export const TrustedRoot = {
  fromJSON(object: any): TrustedRoot {
    return {
      mediaType: isSet(object.mediaType) ? String(object.mediaType) : "",
      tlogs: Array.isArray(object?.tlogs) ? object.tlogs.map((e: any) => TransparencyLogInstance.fromJSON(e)) : [],
      certificateAuthorities: Array.isArray(object?.certificateAuthorities)
        ? object.certificateAuthorities.map((e: any) => CertificateAuthority.fromJSON(e))
        : [],
      ctlogs: Array.isArray(object?.ctlogs)
        ? object.ctlogs.map((e: any) => TransparencyLogInstance.fromJSON(e))
        : [],
      timestampAuthorities: Array.isArray(object?.timestampAuthorities)
        ? object.timestampAuthorities.map((e: any) => CertificateAuthority.fromJSON(e))
        : [],
    };
  },

  toJSON(message: TrustedRoot): unknown {
    const obj: any = {};
    message.mediaType !== undefined && (obj.mediaType = message.mediaType);
    if (message.tlogs) {
      obj.tlogs = message.tlogs.map((e) => e ? TransparencyLogInstance.toJSON(e) : undefined);
    } else {
      obj.tlogs = [];
    }
    if (message.certificateAuthorities) {
      obj.certificateAuthorities = message.certificateAuthorities.map((e) =>
        e ? CertificateAuthority.toJSON(e) : undefined
      );
    } else {
      obj.certificateAuthorities = [];
    }
    if (message.ctlogs) {
      obj.ctlogs = message.ctlogs.map((e) => e ? TransparencyLogInstance.toJSON(e) : undefined);
    } else {
      obj.ctlogs = [];
    }
    if (message.timestampAuthorities) {
      obj.timestampAuthorities = message.timestampAuthorities.map((e) =>
        e ? CertificateAuthority.toJSON(e) : undefined
      );
    } else {
      obj.timestampAuthorities = [];
    }
    return obj;
  },
};

function isSet(value: any): boolean {
  return value !== null && value !== undefined;
}
