package peer

import (
	"log"
)

type IFReader struct {
	Globals
}

func NewIFReader(g Globals) *IFReader {
	return &IFReader{Globals: g}
}

func (r *IFReader) Run() {
	packet := make([]byte, bufferSize)
	for {
		r.handleNextPacket(packet)
	}
}

func (r *IFReader) handleNextPacket(packet []byte) {
	packet = r.readNextPacket(packet)
	remoteIP, ok := r.parsePacket(packet)
	if !ok {
		return
	}
	r.RemotePeers[remoteIP].Load().SendDataTo(packet)
}

func (r *IFReader) readNextPacket(buf []byte) []byte {
	n, err := r.IFace.Read(buf[:cap(buf)])
	if err != nil {
		log.Fatalf("Failed to read from interface: %v", err)
	}

	return buf[:n]
}

// parsePacket returns the VPN ip for the packet, and a boolean indicating
// success.
func (r *IFReader) parsePacket(buf []byte) (byte, bool) {
	n := len(buf)
	if n == 0 {
		return 0, false
	}

	version := buf[0] >> 4

	switch version {
	case 4:
		if n < 20 {
			r.logf("Short IPv4 packet: %d", len(buf))
			return 0, false
		}
		return buf[19], true

	case 6:
		if len(buf) < 40 {
			r.logf("Short IPv6 packet: %d", len(buf))
			return 0, false
		}
		return buf[39], true

	default:
		r.logf("Invalid IP packet version: %v", version)
		return 0, false
	}
}

func (*IFReader) logf(s string, args ...any) {
	log.Printf("[IFReader] "+s, args...)
}
