use std::str::FromStr;

use asn1_rs::{
    BitString, Class, Error, Explicit, Integer,
    OctetString, Oid, Sequence, TaggedValue, ToDer,
};
use base64::{Engine, engine::GeneralPurpose};

const BASE64: GeneralPurpose = base64::engine::general_purpose::STANDARD;

// -----BEGIN PRIVATE KEY-----
// MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDB0n4af3g3zaB67WD+/
// Xe+FNOkwvuoDd/YUPh0y5ZfoBlkqG1WGNkZN2/d4EYqrNrahZANiAAR2vgKLjiAd
// I6l4EAyxGKwGBJ6pAdYZvNlBi8X9kKlCj6aYi5kSKqUfAMaQAX9+0WPoQ6Cy/gzi
// bPPmlPRMa4SdTKgZvvw5nuyNXZQU/wN69Opz/hCqxZHKYx5zSznj4/g=
// -----END PRIVATE KEY-----
//   0 182: SEQUENCE {
//   3   1:   INTEGER 0
//   6  16:   SEQUENCE {
//   8   7:     OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1)
//  17   5:     OBJECT IDENTIFIER secp384r1 (1 3 132 0 34)
//        :     }
//  24 158:   OCTET STRING, encapsulates {
//  27 155:     SEQUENCE {
//  30   1:       INTEGER 1
//  33  48:       OCTET STRING
//        :         74 9F 86 9F DE 0D F3 68 1E BB 58 3F BF 5D EF 85
//        :         34 E9 30 BE EA 03 77 F6 14 3E 1D 32 E5 97 E8 06
//        :         59 2A 1B 55 86 36 46 4D DB F7 78 11 8A AB 36 B6
//  83 100:       [1] {
//  85  98:         BIT STRING
//        :           04 76 BE 02 8B 8E 20 1D 23 A9 78 10 0C B1 18 AC
//        :           06 04 9E A9 01 D6 19 BC D9 41 8B C5 FD 90 A9 42
//        :           8F A6 98 8B 99 12 2A A5 1F 00 C6 90 01 7F 7E D1
//        :           63 E8 43 A0 B2 FE 0C E2 6C F3 E6 94 F4 4C 6B 84
//        :           9D 4C A8 19 BE FC 39 9E EC 8D 5D 94 14 FF 03 7A
//        :           F4 EA 73 FE 10 AA C5 91 CA 63 1E 73 4B 39 E3 E3
//        :           F8
//        :         }
//        :       }
//        :     }
//        :   }

const PRIVATE_KEY: &str = "749F869FDE0DF3681EBB583FBF5DEF8534E930BEEA0377F6143E1D32E597E806592A1B558636464DDBF778118AAB36B6";
const PUBLIC_KEY: &str = "0476BE028B8E201D23A978100CB118AC06049EA901D619BCD9418BC5FD90A9428FA6988B99122AA51F00C690017F7ED16\
3E843A0B2FE0CE26CF3E694F44C6B849D4CA819BEFC399EEC8D5D9414FF037AF4EA73FE10AAC591CA631E734B39E3E3F8";

fn main() {
    let ec_public_key = Oid::from_str("1.2.840.10045.2.1").unwrap();
    let secp_384_r1 = Oid::from_str("1.3.132.0.34").unwrap();

    let private_key_oid_seq = {
        let mut private_key_oid = Vec::new();
        ec_public_key.write_der(&mut private_key_oid).unwrap();
        secp_384_r1.write_der(&mut private_key_oid).unwrap();
        Sequence::new(private_key_oid.into())
    };

    let private_body_seq = {
        let private_key = hex::decode(PRIVATE_KEY).unwrap();
        let public_key = hex::decode(PUBLIC_KEY).unwrap();

        let integer_1 = Integer::from_i8(1);
        let private_key_oct = OctetString::new(&private_key);

        let mut private_body = Vec::new();
        integer_1.write_der(&mut private_body).unwrap();
        private_key_oct.write_der(&mut private_body).unwrap();

        type TaggedValueContextSpecific<'a> = TaggedValue<BitString<'a>, Error, Explicit, { Class::CONTEXT_SPECIFIC }, 1>;
        let public_key_bit = BitString::new(0, &public_key);
        let public_key_tag = TaggedValueContextSpecific::explicit(public_key_bit);
        public_key_tag.write_der(&mut private_body).unwrap();

        Sequence::new(private_body.into())
    };
    let private_body = private_body_seq.to_der_vec().unwrap();
    let private_body_oct = OctetString::new(&private_body);

    let private_key_info_seq = {
        let mut private_key_info = Vec::new();
        let integer_0 = Integer::from_i8(0);
        integer_0.write_der(&mut private_key_info).unwrap();
        private_key_oid_seq.write_der(&mut private_key_info).unwrap();
        private_body_oct.write_der(&mut private_key_info).unwrap();
        Sequence::new(private_key_info.into())
    };

    println!("BASED64:\n{}", BASE64.encode(private_key_info_seq.to_der_vec().unwrap()));
    println!("HEX:\n{}", hex::encode(private_key_info_seq.to_der_vec().unwrap()));
}
