package netbios

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

const (
	NBSS_SESSION_REQUEST           uint8  = 0x81
	NBSS_POSITIVE_SESSION_RESPONSE uint8  = 0x82
	NBSS_NEGATIVE_SESSION_RESPONSE uint8  = 0x83
	ADDR                           string = "192.168.1.202:139"
)

type netBios struct {
	MsgType        uint8
	Flags          uint8 //0-6 : Reserved, must be zero. 7 : Length extension.
	Length         uint16
	CalledNameLen  uint8
	CalledName     [16]uint16
	_              uint8
	CallingNameLen uint8
	CallingName    [16]uint16
	_              uint8
}

type NetBiosMatcher struct {
	packets []*packet.Packet
}

func NewNetBiosMatcher() *NetBiosMatcher {

	nbssMatcher := &NetBiosMatcher{}

	tempBuf := new(bytes.Buffer)
	binary.Write(tempBuf, binary.BigEndian, netBios{})

	query := netBios{
		MsgType:        NBSS_SESSION_REQUEST,
		Flags:          0x00,
		Length:         0x4400,
		CalledNameLen:  0x20,
		CallingNameLen: 0x20,
	}

	query.CalledName[0] = 0x4D45 // L
	query.CalledName[1] = 0x4745 // F

	query.CallingName[0] = 0x4D45
	query.CallingName[1] = 0x4745

	for i := 2; i < 16; i++ {
		query.CalledName[i] = 0x4143 //Space
		query.CallingName[i] = 0x4143
	}
	writer := new(bytes.Buffer)
	binary.Write(writer, binary.LittleEndian, query)

	nbssMatcher.packets = append(nbssMatcher.packets, packet.NewPacket(writer.Bytes(), writer.Len()))

	return nbssMatcher
}

func (t *NetBiosMatcher) ServiceName() string {
	return "NBSS"
}

func (t *NetBiosMatcher) PacketCount() int {
	return len(t.packets)
}
func (t *NetBiosMatcher) Packet(index int) *packet.Packet {
	return t.packets[index]
}

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

func (t *NetBiosMatcher) IsNoResponse(index int) bool {
	return false
}

func (t *NetBiosMatcher) IsPrePacket() bool {
	return false
}

func (t *NetBiosMatcher) Match(index int, packet *packet.Packet, info *types.ServiceScanInfo) bool {

	if packet == nil {
		return false
	}

	reader := new(bytes.Buffer)
	reader.Write(packet.Buffer)

	n := netBios{}
	if err := binary.Read(reader, binary.LittleEndian, &n); err != nil {
		return false
	}

	if NBSS_NEGATIVE_SESSION_RESPONSE != n.MsgType {
		return false
	}

	return true

}
