// Copyright 2018 The Fuchsia 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 main

import (
	"context"
	"fmt"
	"log"
	"net"
	"strings"
	"time"

	"go.fuchsia.dev/fuchsia/tools/net/mdns"
	"go.fuchsia.dev/fuchsia/tools/net/netboot"
)

type deviceFinderBase struct {
	cmd *devFinderCmd
}

type mdnsFinder struct {
	deviceFinderBase
}

const fuchsiaMDNSService = "_fuchsia._udp.local"

func parseAnswer(cmd *devFinderCmd, a mdns.Record, resp mDNSResponse) *fuchsiaDevice {
	if a.Class == mdns.IN && (a.Type == mdns.A || a.Type == mdns.AAAA) &&
		(len(a.Data) == net.IPv4len || len(a.Data) == net.IPv6len) {
		localStr := ".local"
		strIdx := strings.Index(a.Domain, localStr)
		// Determines if ".local" is on the end of the string.
		if strIdx == -1 || strIdx != len(a.Domain)-len(localStr) {
			return nil
		}
		// Trims off localStr for proper formatting.
		fuchsiaDomain := a.Domain[:strIdx]
		if len(fuchsiaDomain) == 0 {
			return &fuchsiaDevice{err: fmt.Errorf("fuchsia domain empty: %q", a.Domain)}
		}
		fdev := &fuchsiaDevice{
			addr:   net.IP(a.Data),
			domain: fuchsiaDomain,
		}
		fdev.zone = resp.devAddr.(*net.UDPAddr).Zone
		if cmd.localResolve {
			var err error
			fdev, err = fdev.outbound()
			if err != nil {
				return &fuchsiaDevice{err: err}
			}
		}
		return fdev
	}
	return nil
}

func listMDNSHandler(cmd *devFinderCmd, resp mDNSResponse, f chan<- *fuchsiaDevice) {
	if len(resp.rxPacket.Answers) == 0 {
		return
	}
	a := resp.rxPacket.Answers[0]
	if a.Class != mdns.IN || a.Type != mdns.PTR || a.Domain != fuchsiaMDNSService {
		return
	}
	// fxbug.dev/6296: Some protection against malformed responses.
	if len(a.Data) == 0 {
		log.Print("Empty data in response. Ignoring...")
		return
	}
	nameLength := int(a.Data[0])
	if len(a.Data) < nameLength+1 {
		log.Printf("Too short data in response. Got %d bytes; expected %d", len(a.Data), nameLength+1)
		return
	}

	for _, a := range resp.rxPacket.Additional {
		fdev := parseAnswer(cmd, a, resp)
		if fdev != nil {
			f <- fdev
		}
	}
}

func (m *mdnsFinder) list(ctx context.Context, f chan *fuchsiaDevice) error {
	listPacket := mdns.Packet{
		Header: mdns.Header{QDCount: 1},
		Questions: []mdns.Question{
			{
				Domain:  fuchsiaMDNSService,
				Type:    mdns.PTR,
				Class:   mdns.IN,
				Unicast: false,
			},
		},
	}
	return m.cmd.sendMDNSPacket(ctx, listPacket, f)
}

func (m *mdnsFinder) resolve(ctx context.Context, f chan *fuchsiaDevice, domains ...string) error {
	// Note: domains is ignored for mdns, and is filtered by the cmd filter callback.
	return m.list(ctx, f)
}

func (m *mdnsFinder) close() {}

type netbootFinder struct {
	deviceFinderBase
}

func (n *netbootFinder) list(ctx context.Context, f chan *fuchsiaDevice) error {
	if !n.cmd.ipv6 {
		return fmt.Errorf("netboot finder is ipv6 only")
	}
	return n.resolve(ctx, f, netboot.NodenameWildcard)
}

func (n *netbootFinder) resolve(ctx context.Context, f chan *fuchsiaDevice, nodenames ...string) error {
	if !n.cmd.ipv6 {
		return fmt.Errorf("netboot finder is ipv6 only")
	}
	ctx, cancel := context.WithTimeout(ctx, n.cmd.timeout)

	// Timeout isn't really used for this application of the client, so
	// just pick an arbitrary timeout.
	c := n.cmd.newNetbootClient(time.Second)
	t := make(chan *netboot.Target, 1024)
	for _, nodename := range nodenames {
		cleanup, err := c.StartDiscover(ctx, t, nodename)
		if err != nil {
			return fmt.Errorf("netboot client setup: %v", err)
		}
		go func() {
			defer cancel()
			defer cleanup()
			for {
				select {
				case target := <-t:
					if target.Error != nil {
						f <- &fuchsiaDevice{
							err: target.Error,
						}
						return
					}
					zone := ""
					if target.Interface != nil {
						zone = target.Interface.Name
					}
					addr := target.TargetAddress
					fdev := &fuchsiaDevice{
						addr:   addr,
						domain: target.Nodename,
						zone:   zone,
					}
					if n.cmd.localResolve {
						var err error
						fdev, err = fdev.outbound()
						if err != nil {
							f <- &fuchsiaDevice{err: err}
							return
						}
					}
					f <- fdev
				case <-ctx.Done():
					return
				}
			}
		}()
	}
	return nil
}

func (n *netbootFinder) close() {}
