import 'dart:typed_data';

import '../types/enum_method.dart';
import 'asn1_decoder.dart';
import 'asn1_der_encoder.dart';
import 'asn1_object.dart';
import 'oid.dart';

class X509PublicKey {
  ASN1Object? pkBlock;

  X509PublicKey({this.pkBlock});

  String? get algOid => pkBlock?.subAtIndex(0)?.subAtIndex(0)?.value;

  String? get algName => OID.fromValue(algOid)?.name();

  String? get algParams => pkBlock?.subAtIndex(0)?.subAtIndex(1)?.value;

  Uint8List? get derEncodedKey {
    var value = pkBlock?.encoded;
    if (value != null) {
      return ASN1DEREncoder.encodeSequence(content: value);
    }
    return null;
  }

  Uint8List? get encoded {
    var oid = OID.fromValue(algOid);
    var keyData = pkBlock?.subAtIndex(1)?.value ?? null;

    if (oid != null && algOid != null && keyData != null) {
      if (oid == OID.ecPublicKey) {
        return Uint8List.fromList(keyData);
      } else if (oid == OID.rsaEncryption) {
        List<ASN1Object>? publicKeyAsn1Objects;
        try {
          publicKeyAsn1Objects = ASN1DERDecoder.decode(
            data: keyData.toList(growable: true),
          );
        } catch (e) {}

        if (publicKeyAsn1Objects != null && publicKeyAsn1Objects.length > 0) {
          var publicKeyModulus = publicKeyAsn1Objects.first
              .subAtIndex(0)
              ?.value;
          if (publicKeyModulus != null) {
            return Uint8List.fromList(publicKeyModulus);
          }
        }
      }
    }
    return null;
  }

  Map<String, dynamic> toMap({EnumMethod? enumMethod}) {
    return {
      "algOid": algOid,
      "algName": algName,
      "algParams": algParams,
      "encoded": encoded,
    };
  }

  Map<String, dynamic> toJson() {
    return toMap();
  }
}
