// Copyright 2017 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.

// +build !build_with_native_toolchain

package ifconfig

import (
	"context"
	"fmt"
	"net"
	"os"
	"strconv"
	"strings"
	"syscall/zx"

	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/fidlconv"
	"go.fuchsia.dev/fuchsia/src/lib/component"

	netfidl "fidl/fuchsia/net"
	"fidl/fuchsia/net/dhcp"
	"fidl/fuchsia/netstack"

	"gvisor.dev/gvisor/pkg/tcpip"
)

type netstackClientApp struct {
	ctx      *component.Context
	netstack *netstack.NetstackWithCtxInterface
}

func (a *netstackClientApp) printAll() {
	ifaces, err := a.netstack.GetInterfaces2(context.Background())
	if err != nil {
		fmt.Print("ifconfig: failed to fetch interfaces\n")
		return
	}

	for _, iface := range ifaces {
		a.printIface(iface)
	}
}

func getIfaceByNameFromIfaces(name string, ifaces []netstack.NetInterface2) *netstack.NetInterface2 {
	var candidate *netstack.NetInterface2
	for i, iface := range ifaces {
		if strings.HasPrefix(iface.Name, name) {
			if candidate != nil {
				return nil
			}
			candidate = &ifaces[i]
		}
	}
	return candidate
}

func getIfaceByIdFromIfaces(id uint32, ifaces []netstack.NetInterface2) *netstack.NetInterface2 {
	for _, iface := range ifaces {
		if iface.Id == id {
			return &iface
		}
	}
	return nil
}

func (a *netstackClientApp) printIface(iface netstack.NetInterface2) {
	fmt.Printf("%s\tHWaddr %s Id:%d\n", iface.Name, hwAddrToString(iface.Hwaddr), iface.Id)
	fmt.Printf("\tinet addr:%s  Bcast:%s  Mask:%s\n", netAddrToString(iface.Addr), netAddrToString(iface.Broadaddr), netAddrToString(iface.Netmask))
	for _, addr := range iface.Ipv6addrs {
		// TODO: scopes
		fmt.Printf("\tinet6 addr: %s/%d Scope:Link\n", netAddrToString(addr.Addr), addr.PrefixLen)
	}
	fmt.Printf("\tmetric:%d\n", iface.Metric)
	fmt.Printf("\t%s\n", iface.Flags)
}

func (a *netstackClientApp) setStatus(iface netstack.NetInterface2, up bool) {
	a.netstack.SetInterfaceStatus(context.Background(), iface.Id, up)
}

func (a *netstackClientApp) addIfaceAddress(iface netstack.NetInterface2, cidr string) {
	netAddr, prefixLen := validateCidr(os.Args[3])
	result, _ := a.netstack.SetInterfaceAddress(context.Background(), iface.Id, netAddr, prefixLen)
	if result.Status != netstack.StatusOk {
		fmt.Printf("Error setting interface address: %s\n", result.Message)
	}
}

func (a *netstackClientApp) removeIfaceAddress(iface netstack.NetInterface2, cidr string) {
	netAddr, prefixLen := validateCidr(os.Args[3])
	result, _ := a.netstack.RemoveInterfaceAddress(context.Background(), iface.Id, netAddr, prefixLen)
	if result.Status != netstack.StatusOk {
		fmt.Printf("Error setting interface address: %s\n", result.Message)
	}
}

func (a *netstackClientApp) parseRouteAttribute(in *netstack.RouteTableEntry2, args []string) (remaining []string, err error) {
	if len(args) < 2 {
		return args, fmt.Errorf("not enough args to make attribute")
	}
	var attr, val string
	switch attr, val, remaining = args[0], args[1], args[2:]; attr {
	case "gateway":
		gateway := toIpAddress(net.ParseIP(val))
		in.Gateway = &gateway
	case "metric":
		m, err := strconv.ParseUint(val, 10, 32)
		if err != nil {
			return remaining, fmt.Errorf("metric value '%s' is not uint32: %s", val, err)
		}
		in.Metric = uint32(m)
	case "iface":
		ifaces, err := a.netstack.GetInterfaces2(context.Background())
		if err != nil {
			return remaining, err
		}
		iface := getIfaceByNameFromIfaces(val, ifaces)
		if err != nil {
			return remaining, err
		}
		if iface == nil {
			return remaining, fmt.Errorf("no such interface '%s'\n", val)
		}

		in.Nicid = iface.Id
	default:
		return remaining, fmt.Errorf("unknown route attribute: %s %s", attr, val)
	}

	return remaining, nil
}

func (a *netstackClientApp) newRouteFromArgs(args []string) (route netstack.RouteTableEntry2, err error) {
	destination, remaining := args[0], args[1:]
	_, dstSubnet, err := net.ParseCIDR(destination)
	if err != nil {
		return route, fmt.Errorf("invalid destination (destination must be provided in CIDR format): %s", destination)
	}

	route.Destination = toIpAddress(dstSubnet.IP)
	route.Netmask = toIpAddress(net.IP(dstSubnet.Mask))

	for len(remaining) > 0 {
		remaining, err = a.parseRouteAttribute(&route, remaining)
		if err != nil {
			return route, err
		}
	}

	if len(remaining) != 0 {
		return route, fmt.Errorf("could not parse all route arguments. remaining: %s", remaining)
	}

	return route, nil
}

func (a *netstackClientApp) addRoute(r netstack.RouteTableEntry2) error {
	if r.Gateway == nil && r.Nicid == 0 {
		return fmt.Errorf("either gateway or iface must be provided when adding a route")
	}

	req, transactionInterface, err := netstack.NewRouteTableTransactionWithCtxInterfaceRequest()
	if err != nil {
		return fmt.Errorf("could not make a new route table transaction: %s", err)
	}
	defer req.Close()
	status, err := a.netstack.StartRouteTableTransaction(context.Background(), req)
	if err != nil || zx.Status(status) != zx.ErrOk {
		return fmt.Errorf("could not start a route table transaction: %s (%s)", err, zx.Status(status))
	}

	status, err = transactionInterface.AddRoute(context.Background(), r)
	if err != nil {
		return fmt.Errorf("could not add route due to transaction interface error: %s", err)
	}
	if zx.Status(status) != zx.ErrOk {
		return fmt.Errorf("could not add route in netstack: %s", zx.Status(status))
	}
	return nil
}

func (a *netstackClientApp) deleteRoute(r netstack.RouteTableEntry2) error {
	req, transactionInterface, err := netstack.NewRouteTableTransactionWithCtxInterfaceRequest()
	if err != nil {
		return fmt.Errorf("could not make a new route table transaction: %s", err)
	}
	defer req.Close()
	status, err := a.netstack.StartRouteTableTransaction(context.Background(), req)
	if err != nil || zx.Status(status) != zx.ErrOk {
		return fmt.Errorf("could not start a route table transaction (maybe the route table is locked?): %s", err)
	}

	status, err = transactionInterface.DelRoute(context.Background(), r)
	if err != nil {
		return fmt.Errorf("could not delete route due to transaction interface error: %s", err)
	}
	if zx.Status(status) != zx.ErrOk {
		return fmt.Errorf("could not delete route in netstack: %s", zx.Status(status))
	}
	return nil
}

func routeTableEntryToString(r netstack.RouteTableEntry2, ifaces []netstack.NetInterface2) string {
	iface := getIfaceByIdFromIfaces(r.Nicid, ifaces)
	var ifaceName string
	if iface == nil {
		ifaceName = fmt.Sprintf("Nicid:%d", r.Nicid)
	} else {
		ifaceName = iface.Name
	}
	var netAndMask net.IPNet
	switch r.Destination.Which() {
	case netfidl.IpAddressIpv4:
		netAndMask = net.IPNet{IP: r.Destination.Ipv4.Addr[:], Mask: r.Netmask.Ipv4.Addr[:]}
	case netfidl.IpAddressIpv6:
		netAndMask = net.IPNet{IP: r.Destination.Ipv6.Addr[:], Mask: r.Netmask.Ipv6.Addr[:]}
	}
	if r.Gateway != nil {
		return fmt.Sprintf("%s via %s %s metric %v", netAndMask.String(), netAddrToString(*r.Gateway), ifaceName, r.Metric)
	}
	return fmt.Sprintf("%s via %s metric %v", netAndMask.String(), ifaceName, r.Metric)
}

func (a *netstackClientApp) showRoutes() error {
	rs, err := a.netstack.GetRouteTable2(context.Background())
	if err != nil {
		return fmt.Errorf("Could not get route table from netstack: %s", err)
	}
	ifaces, err := a.netstack.GetInterfaces2(context.Background())
	if err != nil {
		return err
	}
	for _, r := range rs {
		fmt.Printf("%s\n", routeTableEntryToString(r, ifaces))
	}
	return nil
}

func (a *netstackClientApp) bridge(ifNames []string) (uint32, error) {
	ifs := make([]*netstack.NetInterface2, len(ifNames))
	nicIDs := make([]uint32, len(ifNames))
	// first, validate that all interfaces exist
	ifaces, err := a.netstack.GetInterfaces2(context.Background())
	if err != nil {
		return 0, err
	}
	for i, ifName := range ifNames {
		iface := getIfaceByNameFromIfaces(ifName, ifaces)
		if iface == nil {
			return 0, fmt.Errorf("no such interface '%s'\n", ifName)
		}
		ifs[i] = iface
		nicIDs[i] = iface.Id
	}

	result, nicid, _ := a.netstack.BridgeInterfaces(context.Background(), nicIDs)
	if result.Status != netstack.StatusOk {
		return 0, fmt.Errorf("error bridging interfaces: %s, result: %s", ifNames, result)
	}

	return nicid, nil
}

func (a *netstackClientApp) setDHCP(iface netstack.NetInterface2, startStop string) error {
	req, client, err := dhcp.NewClientWithCtxInterfaceRequest()
	if err != nil {
		return err
	}

	res, err := a.netstack.GetDhcpClient(context.Background(), iface.Id, req)
	if err != nil {
		return err
	}

	switch res.Which() {
	case netstack.NetstackGetDhcpClientResultErr:
		return fmt.Errorf("failed to get DHCP client controller for interface %d: %s", iface.Id, zx.Status(res.Err))
	case netstack.NetstackGetDhcpClientResultResponse:
	}

	switch startStop {
	case "start":
		res, err := client.Start(context.Background())
		if err != nil {
			return fmt.Errorf("failed to start client: %w", err)
		}
		switch res.Which() {
		case dhcp.ClientStartResultErr:
			return &zx.Error{Text: "dhcp client.Start()", Status: zx.Status(res.Err)}
		case dhcp.ClientStartResultResponse:
		}
	case "stop":
		res, err := client.Stop(context.Background())
		if err != nil {
			return fmt.Errorf("failed to stop client: %w", err)
		}
		switch res.Which() {
		case dhcp.ClientStopResultErr:
			return &zx.Error{Text: "dhcp client.Stop()", Status: zx.Status(res.Err)}
		case dhcp.ClientStopResultResponse:
		}
	default:
		usage()
	}

	return nil
}

func hwAddrToString(hwaddr []uint8) string {
	var b strings.Builder
	for i, d := range hwaddr {
		if i > 0 {
			b.WriteByte(':')
		}
		fmt.Fprintf(&b, "%02x", d)
	}
	return b.String()
}

func netAddrToString(addr netfidl.IpAddress) string {
	return fidlconv.ToTCPIPAddress(addr).String()
}

func toIpAddress(addr net.IP) netfidl.IpAddress {
	// TODO(eyalsoha): this doesn't correctly handle IPv6-mapped IPv4 addresses.
	if ipv4 := addr.To4(); ipv4 != nil {
		addr = ipv4
	}
	return fidlconv.ToNetIpAddress(tcpip.Address(addr))
}

func validateCidr(cidr string) (address netfidl.IpAddress, prefixLength uint8) {
	netAddr, netSubnet, err := net.ParseCIDR(cidr)
	if err != nil {
		fmt.Printf("Error parsing CIDR notation: %s, error: %v\n", cidr, err)
		usage()
	}
	prefixLen, _ := netSubnet.Mask.Size()

	return toIpAddress(netAddr), uint8(prefixLen)
}

// bytesToString returns a human-friendly display of the given byte count.
// Values over 1K have an approximation appended in parentheses.
// bytesToString(42) => "42"
// bytesToString(42*1024 + 200) => "43208 (42.2 KB)"
func bytesToString(bytes uint64) string {
	if bytes == 0 {
		return "0"
	}

	units := "BKMGT"
	unitSize := uint64(1)
	unit := "B"

	for i := 0; i+1 < len(units) && bytes >= unitSize*1024; i++ {
		unitSize *= 1024
		unit = string(units[i+1]) + "B"
	}

	if unitSize == 1 {
		return fmt.Sprintf("%d", bytes)
	} else {
		value := float32(bytes) / float32(unitSize)
		return fmt.Sprintf("%d (%.1f %s)", bytes, value, unit)
	}
}

func usage() {
	fmt.Printf("Usage:\n")
	fmt.Printf("  %s [<interface>]\n", os.Args[0])
	fmt.Printf("  %s <interface> {up|down}\n", os.Args[0])
	fmt.Printf("  %s <interface> {add|del} <address>/<mask>\n", os.Args[0])
	fmt.Printf("  %s <interface> metric <metric>\n", os.Args[0])
	fmt.Printf("  %s <interface> dhcp {start|stop}\n", os.Args[0])
	fmt.Printf("  %s route {add|del} <address>/<mask> [iface <name>] [gateway <address>] [metric <metric>]\n", os.Args[0])
	fmt.Printf("  %s route show\n", os.Args[0])
	fmt.Printf("  %s bridge [<interface>]+\n", os.Args[0])
	os.Exit(1)
}

func Main() {
	a := &netstackClientApp{ctx: component.NewContextFromStartupInfo()}
	req, pxy, err := netstack.NewNetstackWithCtxInterfaceRequest()
	if err != nil {
		panic(err.Error())
	}
	a.netstack = pxy
	defer a.netstack.Close()
	a.ctx.ConnectToEnvService(req)

	if len(os.Args) == 1 {
		a.printAll()
		return
	}

	var iface *netstack.NetInterface2
	switch os.Args[1] {
	case "route":
		if len(os.Args) == 2 || os.Args[2] == "show" {
			err = a.showRoutes()
			if err != nil {
				fmt.Printf("Error showing routes: %s\n", err)
			}
			return
		}
		if len(os.Args) < 4 {
			fmt.Printf("Not enough arguments to `ifconfig route`; at least a destination and one of iface name or gateway must be provided\n")
			usage()
		}
		routeFlags := os.Args[3:]
		r, err := a.newRouteFromArgs(routeFlags)
		if err != nil {
			fmt.Printf("Error parsing route from args: %s, error: %s\n", routeFlags, err)
			usage()
		}

		op := os.Args[2]
		switch op {
		case "add":
			if err = a.addRoute(r); err != nil {
				fmt.Printf("Error adding route to route table: %s\n", err)
				usage()
			}
		case "del":
			err = a.deleteRoute(r)
			if err != nil {
				fmt.Printf("Error deleting route from route table: %s\n", err)
				usage()
			}
		default:
			fmt.Printf("Unknown route operation: %s\n", op)
			usage()
		}

		return
	case "bridge":
		ifaces := os.Args[2:]
		nicid, err := a.bridge(ifaces)
		if err != nil {
			fmt.Printf("error creating bridge: %s\n", err)
		} else {
			interfaces, _ := a.netstack.GetInterfaces2(context.Background())
			bridge := getIfaceByIdFromIfaces(uint32(nicid), interfaces)
			fmt.Printf("Bridged interfaces %s.\nInterface '%s' created.\nPlease run `ifconfig %[2]s up` to enable it.\n", ifaces, bridge.Name)
		}
		return
	case "help":
		usage()
		return
	default:
		ifaces, err := a.netstack.GetInterfaces2(context.Background())
		if err != nil {
			fmt.Printf("Error finding interface name: %s\n", err)
			return
		}
		iface = getIfaceByNameFromIfaces(os.Args[1], ifaces)
		if err != nil {
			fmt.Printf("Error finding interface name: %s\n", err)
			return
		}
		if iface == nil {
			fmt.Printf("ifconfig: no such interface '%s'\n", os.Args[1])
			return
		}
	}

	switch len(os.Args) {
	case 2:
		a.printIface(*iface)
	case 3:
		switch os.Args[2] {
		case "up":
			a.setStatus(*iface, true)
		case "down":
			a.setStatus(*iface, false)
		default:
			usage()
		}
	case 4:
		switch os.Args[2] {
		case "add":
			a.addIfaceAddress(*iface, os.Args[3])
		case "del":
			a.removeIfaceAddress(*iface, os.Args[3])
		case "dhcp":
			if err := a.setDHCP(*iface, os.Args[3]); err != nil {
				fmt.Printf("ifconfig: a.setDHCP(%+v, %s) failed: %s", *iface, os.Args[3], err)
			}
		case "metric":
			metric, err := strconv.ParseUint(os.Args[3], 10, 32)
			if err != nil {
				fmt.Printf("ifconfig: metric value '%s' is not uint32: %s\n", os.Args[3], err)
				return
			}
			a.netstack.SetInterfaceMetric(context.Background(), iface.Id, uint32(metric))
		default:
			usage()
		}

	default:
		usage()
	}
}
