package telnet

import (
	"git.loafle.net/overflow/overflow_probe/discovery/core/scan/service/matcher/packet"
	"git.loafle.net/overflow/overflow_probe/discovery/discovery/types"
)

const (
	DO   = 0xfd
	WONT = 0x4b
	WILL = 0xfb
	DONT = 0xfe
	CMD  = 0xff
)

type TelnetMatcher struct {
	sendPackets []*packet.Packet
}

func (tel *TelnetMatcher) Match(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
	result := false

	if packet == nil || packet.Buffer == nil || packet.Len == 0 {
		return result
	}

	buf := make([]byte, 0, 0)
	count := 0

	for i := 0; i < len(packet.Buffer); i++ {
		if packet.Buffer[i] > 0 {
			buf = append(buf, packet.Buffer[i])
		} else if count > 2 {
			break
		} else {
			count++
		}
	}

	for idx := 0; idx < len(buf); idx += 3 {
		if buf[idx] == CMD && (buf[idx+1] == DO || buf[idx+1] == WONT || buf[idx+1] == WILL || buf[idx+1] == DONT) {
			result = true
		} else {
			result = false
		}
	}

	return result
}

func (tel *TelnetMatcher) PacketCount() int {
	return len(tel.sendPackets)
}

func (tel *TelnetMatcher) Packet(index int) *packet.Packet {
	return tel.sendPackets[index]
}

func (tel *TelnetMatcher) ServiceName() string {
	return "Telnet"
}

func (tel *TelnetMatcher) IsError(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {
	return false
}

func (tel *TelnetMatcher) IsNoResponse(index int) bool {
	return false
}

func (tel *TelnetMatcher) IsPrePacket() bool {
	return true
}

func NewTelnetMatcher() *TelnetMatcher {
	r := TelnetMatcher{}

	return &r
}
