// Copyright 2023 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package zstd

// window stores up to size bytes of data.
// It is implemented as a circular buffer:
// sequential save calls append to the data slice until
// its length reaches configured size and after that,
// save calls overwrite previously saved data at off
// and update off such that it always points at
// the byte stored before others.
type window struct {
	size int
	data []byte
	off  int
}

// reset clears stored data and configures window size.
func ( *window) ( int) {
	.data = .data[:0]
	.off = 0
	.size = 
}

// len returns the number of stored bytes.
func ( *window) () uint32 {
	return uint32(len(.data))
}

// save stores up to size last bytes from the buf.
func ( *window) ( []byte) {
	if .size == 0 {
		return
	}
	if len() == 0 {
		return
	}

	if len() >= .size {
		 := len() - .size
		.data = append(.data[:0], [:]...)
		.off = 0
		return
	}

	// Update off to point to the oldest remaining byte.
	 := .size - len(.data)
	if  == 0 {
		 := copy(.data[.off:], )
		if  == len() {
			.off += 
		} else {
			.off = copy(.data, [:])
		}
	} else {
		if  >= len() {
			.data = append(.data, ...)
		} else {
			.data = append(.data, [:]...)
			.off = copy(.data, [:])
		}
	}
}

// appendTo appends stored bytes between from and to indices to the buf.
// Index from must be less or equal to index to and to must be less or equal to w.len().
func ( *window) ( []byte, ,  uint32) []byte {
	 := uint32(len(.data))
	 += uint32(.off)
	 += uint32(.off)

	 := false
	if  >  {
		 -= 
		 = !
	}
	if  >  {
		 -= 
		 = !
	}

	if  {
		 = append(, .data[:]...)
		return append(, .data[:]...)
	} else {
		return append(, .data[:]...)
	}
}