//go:build android
// +build android

package Android

import (
	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"os"
)

var serializeOpts = gopacket.SerializeOptions{
	FixLengths:       true,
	ComputeChecksums: true,
}

func sendIPv4(ip *layers.IPv4, tcp *layers.TCP, payload []byte) []byte {
	_ = tcp.SetNetworkLayerForChecksum(ip)
	buf := gopacket.NewSerializeBuffer()
	if payload != nil && len(payload) > 0 {
		if err := gopacket.SerializeLayers(buf, serializeOpts, ip, tcp, gopacket.Payload(payload)); err != nil {
			return nil
		}
	} else {
		if err := gopacket.SerializeLayers(buf, serializeOpts, ip, tcp); err != nil {
			return nil
		}
	}
	return buf.Bytes()
}

func sendIPv6(ip *layers.IPv6, tcp *layers.TCP, payload []byte) []byte {
	_ = tcp.SetNetworkLayerForChecksum(ip)
	buf := gopacket.NewSerializeBuffer()
	if payload != nil && len(payload) > 0 {
		if err := gopacket.SerializeLayers(buf, serializeOpts, ip, tcp, gopacket.Payload(payload)); err != nil {
			return nil
		}
	} else {
		if err := gopacket.SerializeLayers(buf, serializeOpts, ip, tcp); err != nil {
			return nil
		}
	}
	return buf.Bytes()
}

// SendSynAckToClient ：收到 client SYN 时注入 SYN/ACK（伪造 server 的 SYN/ACK）
func SendSynAckToClient(h *os.File, d *DevConn, clientISN uint32) (int, error) {

	if d.v4 {
		ip := &layers.IPv4{
			Version:  4,
			IHL:      5,
			SrcIP:    d.serverIP,
			DstIP:    d.clientIP,
			Protocol: layers.IPProtocolTCP,
			TTL:      64,
		}
		tcp := &layers.TCP{
			SrcPort: layers.TCPPort(d.serverPort),
			DstPort: layers.TCPPort(d.clientPort),
			Seq:     d.serverISN,
			Ack:     clientISN + 1,
			SYN:     true,
			ACK:     true,
			Window:  65535,
		}
		return h.Write(sendIPv4(ip, tcp, nil))
	}

	ip6 := &layers.IPv6{
		Version:    6,
		SrcIP:      d.serverIP,
		DstIP:      d.clientIP,
		NextHeader: layers.IPProtocolTCP,
		HopLimit:   64,
	}
	tcp6 := &layers.TCP{
		SrcPort: layers.TCPPort(d.serverPort),
		DstPort: layers.TCPPort(d.clientPort),
		Seq:     d.serverISN,
		Ack:     clientISN + 1,
		SYN:     true,
		ACK:     true,
		Window:  65535,
	}
	return h.Write(sendIPv6(ip6, tcp6, nil))
}

func SendAckToKernel(d *DevConn, clientNext uint32) []byte {
	// 只在短时间内持锁读取 seq
	d.mu.Lock()
	seq := d.serverSeqNext
	// copy v4 flag and endpoints
	v4 := d.v4
	serverIP := d.serverIP
	clientIP := d.clientIP
	serverPort := d.serverPort
	clientPort := d.clientPort
	d.mu.Unlock()

	if v4 {
		ip := &layers.IPv4{
			Version:  4,
			IHL:      5,
			SrcIP:    serverIP,
			DstIP:    clientIP,
			Protocol: layers.IPProtocolTCP,
			TTL:      64,
		}
		tcp := &layers.TCP{
			SrcPort: layers.TCPPort(serverPort),
			DstPort: layers.TCPPort(clientPort),
			Seq:     seq,
			Ack:     clientNext,
			ACK:     true,
			Window:  65535,
		}
		bs := sendIPv4(ip, tcp, nil)
		d.mu.Lock()
		if clientNext > d.highestClientAckSent {
			d.highestClientAckSent = clientNext
		}
		d.mu.Unlock()
		return bs
	}

	ip6 := &layers.IPv6{
		Version:    6,
		SrcIP:      serverIP,
		DstIP:      clientIP,
		NextHeader: layers.IPProtocolTCP,
		HopLimit:   64,
	}
	tcp6 := &layers.TCP{
		SrcPort: layers.TCPPort(serverPort),
		DstPort: layers.TCPPort(clientPort),
		Seq:     d.serverSeqNext,
		Ack:     clientNext,
		ACK:     true,
		Window:  65535,
	}
	bs := sendIPv6(ip6, tcp6, nil)
	d.mu.Lock()
	if clientNext > d.highestClientAckSent {
		d.highestClientAckSent = clientNext
	}
	d.mu.Unlock()
	return bs
}

// SendDataToClient ：把伪 server 要发送的数据注入给 client，正确设置 Seq/Ack 并更新 serverSeqNext
func SendDataToClient(d *DevConn, payload []byte) []byte {
	// 读取必要字段（缩短锁持有时间）
	d.mu.Lock()
	seq := d.serverSeqNext
	ack := d.clientNext
	serverIP := d.serverIP
	clientIP := d.clientIP
	serverPort := d.serverPort
	clientPort := d.clientPort
	v4 := d.v4
	d.mu.Unlock()

	if v4 {
		ip := &layers.IPv4{
			Version:  4,
			IHL:      5,
			SrcIP:    serverIP,
			DstIP:    clientIP,
			Protocol: layers.IPProtocolTCP,
			TTL:      64,
		}
		tcp := &layers.TCP{
			SrcPort: layers.TCPPort(serverPort),
			DstPort: layers.TCPPort(clientPort),
			Seq:     seq,
			Ack:     ack,
			ACK:     true,
			PSH:     true,
			Window:  65535,
		}
		bs := sendIPv4(ip, tcp, payload)
		// 更新 serverSeqNext
		d.mu.Lock()
		d.serverSeqNext += uint32(len(payload))
		d.mu.Unlock()
		return bs
	}

	ip6 := &layers.IPv6{
		Version:    6,
		SrcIP:      serverIP,
		DstIP:      clientIP,
		NextHeader: layers.IPProtocolTCP,
		HopLimit:   64,
	}
	tcp6 := &layers.TCP{
		SrcPort: layers.TCPPort(serverPort),
		DstPort: layers.TCPPort(clientPort),
		Seq:     seq,
		Ack:     ack,
		ACK:     true,
		PSH:     true,
		Window:  65535,
	}
	bs := sendIPv6(ip6, tcp6, payload)
	d.mu.Lock()
	d.serverSeqNext += uint32(len(payload))
	d.mu.Unlock()
	return bs
}

// SendFinToClient ：注入一个 FIN/ACK（server -> client），并在成功后把 serverSeqNext 增 1（FIN 消耗 1 序号）。
func SendFinToClient(d *DevConn) []byte {
	// 复制需要的字段，避免在持锁时调用 h.Send 导致死锁或长时间阻塞
	d.mu.Lock()
	seq := d.serverSeqNext
	ack := d.clientNext
	serverIP := d.serverIP
	clientIP := d.clientIP
	serverPort := d.serverPort
	clientPort := d.clientPort
	v4 := d.v4
	d.mu.Unlock()

	if v4 {
		ip := &layers.IPv4{
			Version:  4,
			IHL:      5,
			SrcIP:    serverIP,
			DstIP:    clientIP,
			Protocol: layers.IPProtocolTCP,
			TTL:      64,
		}
		tcp := &layers.TCP{
			SrcPort: layers.TCPPort(serverPort),
			DstPort: layers.TCPPort(clientPort),
			Seq:     seq,
			Ack:     ack,
			FIN:     true,
			ACK:     true,
			Window:  65535,
		}
		bs := sendIPv4(ip, tcp, nil)
		d.mu.Lock()
		if seq == d.serverSeqNext {
			d.serverSeqNext = seq + 1
		}
		d.mu.Unlock()
		return bs
	}

	ip6 := &layers.IPv6{
		Version:    6,
		SrcIP:      serverIP,
		DstIP:      clientIP,
		NextHeader: layers.IPProtocolTCP,
		HopLimit:   64,
	}
	tcp6 := &layers.TCP{
		SrcPort: layers.TCPPort(serverPort),
		DstPort: layers.TCPPort(clientPort),
		Seq:     seq,
		Ack:     ack,
		FIN:     true,
		ACK:     true,
		Window:  65535,
	}
	bs := sendIPv6(ip6, tcp6, nil)
	d.mu.Lock()
	if seq == d.serverSeqNext {
		d.serverSeqNext = seq + 1
	}
	d.mu.Unlock()
	return bs
}

// SendRstToClient ：立刻强制断开（client 会收到 RST），通常客户端会马上重连
func SendRstToClient(d *DevConn) []byte {
	d.mu.Lock()
	seq := d.serverSeqNext
	ack := d.clientNext
	serverIP := d.serverIP
	clientIP := d.clientIP
	serverPort := d.serverPort
	clientPort := d.clientPort
	v4 := d.v4
	d.mu.Unlock()
	if v4 {
		ip := &layers.IPv4{
			Version: 4, IHL: 5,
			SrcIP: serverIP, DstIP: clientIP,
			Protocol: layers.IPProtocolTCP, TTL: 64,
		}
		tcp := &layers.TCP{
			SrcPort: layers.TCPPort(serverPort),
			DstPort: layers.TCPPort(clientPort),
			Seq:     seq,
			Ack:     ack,
			RST:     true,
			Window:  0,
		}
		return sendIPv4(ip, tcp, nil)
	}

	ip6 := &layers.IPv6{
		Version:    6,
		SrcIP:      serverIP,
		DstIP:      clientIP,
		NextHeader: layers.IPProtocolTCP,
		HopLimit:   64,
	}
	tcp6 := &layers.TCP{
		SrcPort: layers.TCPPort(serverPort),
		DstPort: layers.TCPPort(clientPort),
		Seq:     seq,
		Ack:     ack,
		RST:     true,
		Window:  0,
	}
	return sendIPv6(ip6, tcp6, nil)
}
func buildTCPReply(d *DevConn, tcp *layers.TCP, sendAck bool, sendFin bool, sendRst bool) (int, error) {
	var replyIP gopacket.NetworkLayer
	var replyIPop gopacket.SerializableLayer
	if d.v4 {
		ip := &layers.IPv4{
			Version: 4, IHL: 5,
			SrcIP: d.serverIP, DstIP: d.clientIP,
			Protocol: layers.IPProtocolTCP, TTL: 64,
		}
		replyIP = ip
		replyIPop = ip
	} else {
		ip6 := &layers.IPv6{
			Version:    6,
			SrcIP:      d.serverIP,
			DstIP:      d.clientIP,
			NextHeader: layers.IPProtocolTCP,
			HopLimit:   64,
		}
		replyIP = ip6
		replyIPop = ip6
	}

	replyTCP := *tcp

	replyTCP.SrcPort, replyTCP.DstPort = tcp.DstPort, tcp.SrcPort

	// 清空 payload
	replyTCP.Payload = nil

	// 重置标志
	replyTCP.SYN = false
	replyTCP.ACK = sendAck
	replyTCP.FIN = sendFin
	replyTCP.RST = sendRst
	replyTCP.PSH = false
	replyTCP.URG = false
	replyTCP.ECE = false
	replyTCP.CWR = false
	// 序号与确认号
	replyTCP.Seq = tcp.Ack
	replyTCP.Ack = tcp.Seq + uint32(len(tcp.Payload))
	if tcp.SYN || tcp.FIN {
		replyTCP.Ack++
	}
	_ = replyTCP.SetNetworkLayerForChecksum(replyIP)
	buf := gopacket.NewSerializeBuffer()
	opts := gopacket.SerializeOptions{FixLengths: true, ComputeChecksums: true}
	_ = gopacket.SerializeLayers(buf, opts, replyIPop, &replyTCP)
	return d.tun.Write(buf.Bytes())
}
