package internal

import (
	"bytes"
	"math/rand"
	"time"
)

// SNISplitter splits input such that SNI is splitted across
// a bunch of different output buffers.
func SNISplitter(input []byte, sni []byte) (output [][]byte) {
	idx := bytes.Index(input, sni)
	if idx < 0 {
		output = append(output, input)
		return
	}
	output = append(output, input[:idx])
	// TODO(bassosimone): splitting every three bytes causes
	// a bunch of Unicode chatacters (e.g., in Chinese) to be
	// sent as part of the same segment. Is that OK?
	const segmentsize = 3
	var buf []byte
	for _, chr := range input[idx : idx+len(sni)] {
		buf = append(buf, chr)
		if len(buf) == segmentsize {
			output = append(output, buf)
			buf = nil
		}
	}
	if len(buf) > 0 {
		output = append(output, buf)
	}
	output = append(output, input[idx+len(sni):])
	return
}

// Splitter84rest segments the specified buffer into three
// sub-buffers containing respectively 8 bytes, 4 bytes, and
// the rest of the buffer. This segment technique has been
// described by Kevin Bock during the Internet Measurements
// Village 2020: https://youtu.be/ksojSRFLbBM?t=1140.
func Splitter84rest(input []byte) (output [][]byte) {
	if len(input) <= 12 {
		output = append(output, input)
		return
	}
	output = append(output, input[:8])
	output = append(output, input[8:12])
	output = append(output, input[12:])
	return
}

// Splitter3264rand splits the specified buffer at a random
// offset between 32 and 64 bytes. This is the methodology used
// by github.com/Jigsaw-Code/outline-go-tun2socks.
func Splitter3264rand(input []byte) (output [][]byte) {
	if len(input) <= 64 {
		output = append(output, input)
		return
	}
	rnd := rand.New(rand.NewSource(time.Now().UnixNano()))
	offset := rnd.Intn(32) + 32
	output = append(output, input[:offset])
	output = append(output, input[offset:])
	return
}
