package mstypes

import (
	
	
	
	

	
	
)

// Compression format assigned numbers. https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-xca/a8b7cb0a-92a6-4187-a23b-5e14273b96f8
const (
	CompressionFormatNone       uint16 = 0
	CompressionFormatLZNT1      uint16 = 2 // LZNT1 aka ntfs compression
	CompressionFormatXPress     uint16 = 3 // plain LZ77
	CompressionFormatXPressHuff uint16 = 4 // LZ77+Huffman - The Huffman variant of the XPRESS compression format uses LZ77-style dictionary compression combined with Huffman coding.
)

// ClaimsSourceTypeAD https://msdn.microsoft.com/en-us/library/hh553809.aspx
const ClaimsSourceTypeAD uint16 = 1

// Claim Type assigned numbers
const (
	ClaimTypeIDInt64    uint16 = 1
	ClaimTypeIDUInt64   uint16 = 2
	ClaimTypeIDString   uint16 = 3
	ClaimsTypeIDBoolean uint16 = 6
)

// ClaimsBlob implements https://msdn.microsoft.com/en-us/library/hh554119.aspx
type ClaimsBlob struct {
	Size        uint32
	EncodedBlob EncodedBlob
}

// EncodedBlob are the bytes of the encoded Claims
type EncodedBlob []byte

// Size returns the size of the bytes of the encoded Claims
func ( EncodedBlob) ( interface{}) int {
	 := .(ClaimsBlob)
	return int(.Size)
}

// ClaimsSetMetadata implements https://msdn.microsoft.com/en-us/library/hh554073.aspx
type ClaimsSetMetadata struct {
	ClaimsSetSize             uint32
	ClaimsSetBytes            []byte `ndr:"pointer,conformant"`
	CompressionFormat         uint16 // Enum see constants for options
	UncompressedClaimsSetSize uint32
	ReservedType              uint16
	ReservedFieldSize         uint32
	ReservedField             []byte `ndr:"pointer,conformant"`
}

// ClaimsSet reads the ClaimsSet type from the NDR encoded ClaimsSetBytes in the ClaimsSetMetadata
func ( *ClaimsSetMetadata) () ( ClaimsSet,  error) {
	if len(.ClaimsSetBytes) < 1 {
		 = errors.New("no bytes available for ClaimsSet")
		return
	}
	// TODO switch statement to decompress ClaimsSetBytes
	switch .CompressionFormat {
	case CompressionFormatLZNT1:
		 := hex.EncodeToString(.ClaimsSetBytes)
		 = fmt.Errorf("ClaimsSet compressed, format LZNT1 not currently supported: %s", )
		return
	case CompressionFormatXPress:
		 := hex.EncodeToString(.ClaimsSetBytes)
		 = fmt.Errorf("ClaimsSet compressed, format XPress not currently supported: %s", )
		return
	case CompressionFormatXPressHuff:
		var  []byte
		 := bytes.NewBuffer()
		,  := hpack.HuffmanDecode(, .ClaimsSetBytes)
		if  != nil {
			 = fmt.Errorf("error deflating: %v", )
			return
		}
		.ClaimsSetBytes = .Bytes()
	}
	 := ndr.NewDecoder(bytes.NewReader(.ClaimsSetBytes))
	 = .Decode(&)
	return
}

// ClaimsSet implements https://msdn.microsoft.com/en-us/library/hh554122.aspx
type ClaimsSet struct {
	ClaimsArrayCount  uint32
	ClaimsArrays      []ClaimsArray `ndr:"pointer,conformant"`
	ReservedType      uint16
	ReservedFieldSize uint32
	ReservedField     []byte `ndr:"pointer,conformant"`
}

// ClaimsArray implements https://msdn.microsoft.com/en-us/library/hh536458.aspx
type ClaimsArray struct {
	ClaimsSourceType uint16
	ClaimsCount      uint32
	ClaimEntries     []ClaimEntry `ndr:"pointer,conformant"`
}

// ClaimEntry is a NDR union that implements https://msdn.microsoft.com/en-us/library/hh536374.aspx
type ClaimEntry struct {
	ID         string           `ndr:"pointer,conformant,varying"`
	Type       uint16           `ndr:"unionTag"`
	TypeInt64  ClaimTypeInt64   `ndr:"unionField"`
	TypeUInt64 ClaimTypeUInt64  `ndr:"unionField"`
	TypeString ClaimTypeString  `ndr:"unionField"`
	TypeBool   ClaimTypeBoolean `ndr:"unionField"`
}

// SwitchFunc is the ClaimEntry union field selection function
func ( ClaimEntry) ( interface{}) string {
	switch .Type {
	case ClaimTypeIDInt64:
		return "TypeInt64"
	case ClaimTypeIDUInt64:
		return "TypeUInt64"
	case ClaimTypeIDString:
		return "TypeString"
	case ClaimsTypeIDBoolean:
		return "TypeBool"
	}
	return ""
}

// ClaimTypeInt64 is a claim of type int64
type ClaimTypeInt64 struct {
	ValueCount uint32
	Value      []int64 `ndr:"pointer,conformant"`
}

// ClaimTypeUInt64 is a claim of type uint64
type ClaimTypeUInt64 struct {
	ValueCount uint32
	Value      []uint64 `ndr:"pointer,conformant"`
}

// ClaimTypeString is a claim of type string
type ClaimTypeString struct {
	ValueCount uint32
	Value      []LPWSTR `ndr:"pointer,conformant"`
}

// ClaimTypeBoolean is a claim of type bool
type ClaimTypeBoolean struct {
	ValueCount uint32
	Value      []bool `ndr:"pointer,conformant"`
}