// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT

package handshake

import (
	

	
	
	
	
)

/*
MessageCertificateRequest is so a non-anonymous server can optionally
request a certificate from the client, if appropriate for the selected cipher
suite.  This message, if sent, will immediately follow the ServerKeyExchange
message (if it is sent; otherwise, this message follows the
server's Certificate message).

https://tools.ietf.org/html/rfc5246#section-7.4.4
*/
type MessageCertificateRequest struct {
	CertificateTypes            []clientcertificate.Type
	SignatureHashAlgorithms     []signaturehash.Algorithm
	CertificateAuthoritiesNames [][]byte
}

const (
	messageCertificateRequestMinLength = 5
)

// Type returns the Handshake Type
func ( MessageCertificateRequest) () Type {
	return TypeCertificateRequest
}

// Marshal encodes the Handshake
func ( *MessageCertificateRequest) () ([]byte, error) {
	 := []byte{byte(len(.CertificateTypes))}
	for ,  := range .CertificateTypes {
		 = append(, byte())
	}

	 = append(, []byte{0x00, 0x00}...)
	binary.BigEndian.PutUint16([len()-2:], uint16(len(.SignatureHashAlgorithms)*2))
	for ,  := range .SignatureHashAlgorithms {
		 = append(, byte(.Hash))
		 = append(, byte(.Signature))
	}

	// Distinguished Names
	 := 0
	for ,  := range .CertificateAuthoritiesNames {
		 += len() + 2
	}
	 = append(, []byte{0x00, 0x00}...)
	binary.BigEndian.PutUint16([len()-2:], uint16())
	if  > 0 {
		for ,  := range .CertificateAuthoritiesNames {
			 = append(, []byte{0x00, 0x00}...)
			binary.BigEndian.PutUint16([len()-2:], uint16(len()))
			 = append(, ...)
		}
	}
	return , nil
}

// Unmarshal populates the message from encoded data
func ( *MessageCertificateRequest) ( []byte) error {
	if len() < messageCertificateRequestMinLength {
		return errBufferTooSmall
	}

	 := 0
	 := int([0])
	++

	if ( + ) > len() {
		return errBufferTooSmall
	}

	for  := 0;  < ; ++ {
		 := clientcertificate.Type([+])
		if ,  := clientcertificate.Types()[];  {
			.CertificateTypes = append(.CertificateTypes, )
		}
	}
	 += 
	if len() < +2 {
		return errBufferTooSmall
	}
	 := int(binary.BigEndian.Uint16([:]))
	 += 2

	if ( + ) > len() {
		return errBufferTooSmall
	}

	for  := 0;  < ;  += 2 {
		if len() < ( +  + 2) {
			return errBufferTooSmall
		}
		 := hash.Algorithm([+])
		 := signature.Algorithm([++1])

		if ,  := hash.Algorithms()[]; ! {
			continue
		} else if ,  := signature.Algorithms()[]; ! {
			continue
		}
		.SignatureHashAlgorithms = append(.SignatureHashAlgorithms, signaturehash.Algorithm{Signature: , Hash: })
	}

	 += 
	if len() < +2 {
		return errBufferTooSmall
	}
	 := int(binary.BigEndian.Uint16([:]))
	 += 2
	if ( + ) > len() {
		return errBufferTooSmall
	}
	 := make([]byte, )
	copy(, [:+])
	.CertificateAuthoritiesNames = nil
	for len() > 0 {
		if len() < 2 {
			return errBufferTooSmall
		}
		 := binary.BigEndian.Uint16()
		 = [2:]

		if len() < int() {
			return errBufferTooSmall
		}

		.CertificateAuthoritiesNames = append(.CertificateAuthoritiesNames, [:])
		 = [:]
	}

	return nil
}