package ws

import (
	"encoding/binary"
)

// Header size length bounds in bytes.
const (
	MaxHeaderSize = 14
	//MinHeaderSize = 2
)

const (
	bit0 = 0x80
	//bit1 = 0x40
	//bit2 = 0x20
	//bit3 = 0x10
	//bit4 = 0x08
	bit5 = 0x04
	bit6 = 0x02
	bit7 = 0x01

	len7  = int64(125)
	len16 = int64(^(uint16(0)))
	len64 = int64(^(uint64(0)) >> 1)
)

//// HeaderSize returns number of bytes that are needed to encode given header.
//// It returns -1 if header is malformed.
//func HeaderSize(h *Header) (n int) {
//	switch {
//	case h.Length < 126:
//		n = 2
//	case h.Length <= len16:
//		n = 4
//	case h.Length <= len64:
//		n = 10
//	default:
//		return -1
//	}
//	if h.Masked {
//		n += len(h.Mask)
//	}
//	return n
//}

// WriteHeader writes header binary representation into w.
func WriteHeader(h *Header) ([]byte, error) {
	// Make slice of bytes with capacity 14 that could hold any header.
	bts := make([]byte, MaxHeaderSize)

	if h.Fin {
		bts[0] |= bit0
	}
	bts[0] |= h.Rsv << 4
	bts[0] |= byte(h.OpCode)

	var n int
	switch {
	case h.Length <= len7:
		bts[1] = byte(h.Length)
		n = 2

	case h.Length <= len16:
		bts[1] = 126
		binary.BigEndian.PutUint16(bts[2:4], uint16(h.Length))
		n = 4

	case h.Length <= len64:
		bts[1] = 127
		binary.BigEndian.PutUint64(bts[2:10], uint64(h.Length))
		n = 10

	default:
		return nil, ErrHeaderLengthUnexpected
	}

	if h.Masked {
		bts[1] |= bit0
		n += copy(bts[n:], h.Mask[:])
	}

	return bts[:n], nil
}
