// Copyright 2014 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 runner

import (
	"encoding/binary"
	"fmt"
	"io"
	"math"
	"net"
	"slices"
	"time"
)

// opcodePacket signals a packet, encoded with a 32-bit length prefix, followed
// by the payload.
const opcodePacket = byte('P')

// opcodeTimeout signals a read timeout, encoded by a 64-bit number of
// nanoseconds. On receipt, the peer should reply with
// opcodeTimeoutAck. opcodeTimeout may only be sent by the Go side.
const opcodeTimeout = byte('T')

// opcodeTimeoutAck acknowledges a read timeout. This opcode has no payload and
// may only be sent by the C side. Timeout ACKs act as a synchronization point
// at the timeout, to bracket one flight of messages from C.
const opcodeTimeoutAck = byte('t')

// opcodeMTU updates the shim's MTU, encoded as a 32-bit number of bytes.
const opcodeMTU = byte('M')

// opcodeExpectNextTimeout indicates that the shim should report a specified timeout
// to the calling application. The timeout is encoded as in opcodeTimeout, but
// MaxUint64 indicates there should be no timeout.
const opcodeExpectNextTimeout = byte('E')

// opcodeUpdateTimeout update the timeout of the DTLS object.
const opcodeUpdateTimeout = byte('U')

type packetAdaptor struct {
	net.Conn
	debug *recordingConn
}

// newPacketAdaptor wraps a reliable streaming net.Conn into a reliable
// packet-based net.Conn. The stream contains packets and control commands,
// distinguished by a one byte opcode.
func newPacketAdaptor(conn net.Conn) *packetAdaptor {
	return &packetAdaptor{conn, nil}
}

func (p *packetAdaptor) log(message string, data []byte) {
	if p.debug == nil {
		return
	}

	p.debug.LogSpecial(message, data)
}

func (p *packetAdaptor) readOpcode() (byte, error) {
	out := make([]byte, 1)
	if _, err := io.ReadFull(p.Conn, out); err != nil {
		return 0, err
	}
	return out[0], nil
}

func (p *packetAdaptor) readPacketBody() ([]byte, error) {
	var length uint32
	if err := binary.Read(p.Conn, binary.BigEndian, &length); err != nil {
		return nil, err
	}
	out := make([]byte, length)
	if _, err := io.ReadFull(p.Conn, out); err != nil {
		return nil, err
	}
	return out, nil
}

func (p *packetAdaptor) Read(b []byte) (int, error) {
	opcode, err := p.readOpcode()
	if err != nil {
		return 0, err
	}
	if opcode != opcodePacket {
		return 0, fmt.Errorf("unexpected opcode '%d'", opcode)
	}
	out, err := p.readPacketBody()
	if err != nil {
		return 0, err
	}
	return copy(b, out), nil
}

func (p *packetAdaptor) Write(b []byte) (int, error) {
	payload := make([]byte, 1+4+len(b))
	payload[0] = opcodePacket
	binary.BigEndian.PutUint32(payload[1:5], uint32(len(b)))
	copy(payload[5:], b)
	if _, err := p.Conn.Write(payload); err != nil {
		return 0, err
	}
	return len(b), nil
}

// SendReadTimeout instructs the peer to simulate a read timeout. It then waits
// for acknowledgement of the timeout, buffering any packets received since
// then. The packets are then returned.
func (p *packetAdaptor) SendReadTimeout(d time.Duration) ([][]byte, error) {
	p.log("Simulating read timeout: "+d.String(), nil)

	payload := make([]byte, 1+8)
	payload[0] = opcodeTimeout
	binary.BigEndian.PutUint64(payload[1:], uint64(d.Nanoseconds()))
	if _, err := p.Conn.Write(payload); err != nil {
		return nil, err
	}

	var packets [][]byte
	for {
		opcode, err := p.readOpcode()
		if err != nil {
			return nil, err
		}
		switch opcode {
		case opcodeTimeoutAck:
			p.log("Received timeout ACK", nil)
			// Done! Return the packets buffered and continue.
			return packets, nil
		case opcodePacket:
			// Buffer the packet for the caller to process.
			packet, err := p.readPacketBody()
			if err != nil {
				return nil, err
			}
			p.log("Simulating dropped packet", packet)
			packets = append(packets, packet)
		default:
			return nil, fmt.Errorf("unexpected opcode '%d'", opcode)
		}
	}
}

// SetPeerMTU instructs the peer to set the MTU to the specified value.
func (p *packetAdaptor) SetPeerMTU(mtu int) error {
	p.log(fmt.Sprintf("Setting MTU to %d", mtu), nil)

	payload := make([]byte, 1+4)
	payload[0] = opcodeMTU
	binary.BigEndian.PutUint32(payload[1:], uint32(mtu))
	_, err := p.Conn.Write(payload)
	return err
}

// ExpectNextTimeout indicates the peer's next timeout should be d from now.
func (p *packetAdaptor) ExpectNextTimeout(d time.Duration) error {
	payload := make([]byte, 1+8)
	payload[0] = opcodeExpectNextTimeout
	binary.BigEndian.PutUint64(payload[1:], uint64(d.Nanoseconds()))
	_, err := p.Conn.Write(payload)
	return err
}

// ExpectNoNext indicates the peer should not have a next timeout.
func (p *packetAdaptor) ExpectNoNextTimeout() error {
	payload := make([]byte, 1+8)
	payload[0] = opcodeExpectNextTimeout
	binary.BigEndian.PutUint64(payload[1:], math.MaxUint64)
	_, err := p.Conn.Write(payload)
	return err
}

// UpdatePeerTimeout instructs the peer to set the timeoput to the specified value.
func (p *packetAdaptor) SetPeerTimeout(d time.Duration) error {
	p.log(fmt.Sprintf("Setting timeout to to %d ms", d.Milliseconds()), nil)

	payload := make([]byte, 1+4)
	payload[0] = opcodeUpdateTimeout
	binary.BigEndian.PutUint32(payload[1:], uint32(d.Milliseconds()))
	_, err := p.Conn.Write(payload)
	return err
}

type replayAdaptor struct {
	net.Conn
	prevWrite []byte
}

// newReplayAdaptor wraps a packeted net.Conn. It transforms it into
// one which, after writing a packet, always replays the previous
// write.
func newReplayAdaptor(conn net.Conn) net.Conn {
	return &replayAdaptor{Conn: conn}
}

func (r *replayAdaptor) Write(b []byte) (int, error) {
	n, err := r.Conn.Write(b)

	// Replay the previous packet and save the current one to
	// replay next.
	if r.prevWrite != nil {
		r.Conn.Write(r.prevWrite)
	}
	r.prevWrite = append(r.prevWrite[:0], b...)

	return n, err
}

type damageAdaptor struct {
	net.Conn
	damage bool
}

// newDamageAdaptor wraps a packeted net.Conn. It transforms it into one which
// optionally damages the final byte of every Write() call.
func newDamageAdaptor(conn net.Conn) *damageAdaptor {
	return &damageAdaptor{Conn: conn}
}

func (d *damageAdaptor) setDamage(damage bool) {
	d.damage = damage
}

func (d *damageAdaptor) Write(b []byte) (int, error) {
	if d.damage && len(b) > 0 {
		b = slices.Clone(b)
		b[len(b)-1]++
	}
	return d.Conn.Write(b)
}
