package kadmin

import (
	
	
	
	
	

	
	
)

const (
	verisonHex = "ff80"
)

// Request message for changing password.
type Request struct {
	APREQ   messages.APReq
	KRBPriv messages.KRBPriv
}

// Reply message for a password change.
type Reply struct {
	MessageLength int
	Version       int
	APREPLength   int
	APREP         messages.APRep
	KRBPriv       messages.KRBPriv
	KRBError      messages.KRBError
	IsKRBError    bool
	ResultCode    uint16
	Result        string
}

// Marshal a Request into a byte slice.
func ( *Request) () ( []byte,  error) {
	 = []byte{255, 128} // protocol version number: contains the hex constant 0xff80 (big-endian integer).
	,  := .APREQ.Marshal()
	if  != nil {
		 = fmt.Errorf("error marshaling AP_REQ: %v", )
		return
	}
	if len() > math.MaxUint16 {
		 = errors.New("length of AP_REQ greater then max Uint16 size")
		return
	}
	 := make([]byte, 2)
	binary.BigEndian.PutUint16(, uint16(len()))
	 = append(, ...)
	 = append(, ...)
	,  := .KRBPriv.Marshal()
	if  != nil {
		 = fmt.Errorf("error marshaling KRB_Priv: %v", )
		return
	}
	 = append(, ...)
	if len()+2 > math.MaxUint16 {
		 = errors.New("length of message greater then max Uint16 size")
		return
	}
	 := make([]byte, 2)
	binary.BigEndian.PutUint16(, uint16(len()+2))
	 = append(, ...)
	return
}

// Unmarshal a byte slice into a Reply.
func ( *Reply) ( []byte) error {
	.MessageLength = int(binary.BigEndian.Uint16([0:2]))
	.Version = int(binary.BigEndian.Uint16([2:4]))
	if .Version != 1 {
		return fmt.Errorf("kadmin reply has incorrect protocol version number: %d", .Version)
	}
	.APREPLength = int(binary.BigEndian.Uint16([4:6]))
	if .APREPLength != 0 {
		 := .APREP.Unmarshal([6 : 6+.APREPLength])
		if  != nil {
			return 
		}
		 = .KRBPriv.Unmarshal([6+.APREPLength : .MessageLength])
		if  != nil {
			return 
		}
	} else {
		.IsKRBError = true
		.KRBError.Unmarshal([6:.MessageLength])
		.ResultCode, .Result = parseResponse(.KRBError.EData)
	}
	return nil
}

func parseResponse( []byte) ( uint16,  string) {
	 = binary.BigEndian.Uint16([0:2])
	 := bytes.NewBuffer([2:])
	 := make([]byte, len()-2)
	binary.Read(, binary.BigEndian, &)
	 = string()
	return
}

// Decrypt the encrypted part of the KRBError within the change password Reply.
func ( *Reply) ( types.EncryptionKey) error {
	if .IsKRBError {
		return .KRBError
	}
	 := .KRBPriv.DecryptEncPart()
	if  != nil {
		return 
	}
	.ResultCode, .Result = parseResponse(.KRBPriv.DecryptedEncPart.UserData)
	return nil
}