# Copyright (c) 2023 Yuki Kimoto
# MIT License

class Net::SSLeay::X509 : pointer {
  version_from Net::SSLeay;
  allow Net::SSLeay::PEM;
  
  use Net::SSLeay::Error;
  use Net::SSLeay::X509_NAME;
  use Net::SSLeay::EVP_MD;
  use Net::SSLeay::Constant as SSL;
  use Net::SSLeay::ASN1_OBJECT;
  use Net::SSLeay::X509_EXTENSION;
  use Net::SSLeay::EVP_PKEY;
  use Net::SSLeay::ASN1_INTEGER;
  use Net::SSLeay::GENERAL_NAME;
  
  use Fn;
  
  # Class Methods
  native static method new : Net::SSLeay::X509 ();
  
  private static method new_with_pointer : Net::SSLeay::X509 ($pointer : Address, $options : object[] = undef) {
    
    my $self = new Net::SSLeay::X509;
    
    Fn->set_pointer($self, $pointer);
    
    return $self;
  }
  
  native static method check_issued : int ($issuer : Net::SSLeay::X509, $subject : Net::SSLeay::X509);
  
  # Instance Methods
  native method get_serialNumber : Net::SSLeay::ASN1_INTEGER ();
  
  native method get_issuer_name : Net::SSLeay::X509_NAME ();
  
  native method get_subject_name : Net::SSLeay::X509_NAME ();
  
  native method pubkey_digest : int ($type : Net::SSLeay::EVP_MD, $md : mutable string, $len_ref : int*);
  
  method pubkey_digest_return_string : string ($type : Net::SSLeay::EVP_MD) {
    
    my $md = (mutable string)new_string_len SSL->EVP_MAX_MD_SIZE;
    my $len = 0;
    
    $self->pubkey_digest($type, $md, \$len);
    
    Fn->shorten($md, $len);
    
    return $md;
  }
  
  native method get_ext_by_NID : int ($nid : int, $lastpos : int = 0);
  
  native method get_ext_count : int ();
  
  native method get_ext : Net::SSLeay::X509_EXTENSION ($loc : int);
  
  native method get_subjectAltNames : Net::SSLeay::GENERAL_NAME[] ();
  
  native method digest : int ($type : Net::SSLeay::EVP_MD, $md : mutable string, $len_ref : int*);
  
  method digest_return_string : string ($type : Net::SSLeay::EVP_MD) {
    
    my $md = (mutable string)new_string_len SSL->EVP_MAX_MD_SIZE;
    my $len = 0;
    
    $self->digest($type, $md, \$len);
    
    Fn->shorten($md, $len);
    
    return $md;
  }
  
  native method dup : Net::SSLeay::X509 ();
  
  native method DESTROY : void ();
  
}