// Copyright 2016 The Go 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 net

import (
	"errors"
	"internal/itoa"
	"os"
)

// If the ifindex is zero, interfaceTable returns mappings of all
// network interfaces. Otherwise it returns a mapping of a specific
// interface.
func interfaceTable(ifindex int) ([]Interface, error) {
	if ifindex == 0 {
		n, err := interfaceCount()
		if err != nil {
			return nil, err
		}
		ifcs := make([]Interface, n)
		for i := range ifcs {
			ifc, err := readInterface(i)
			if err != nil {
				return nil, err
			}
			ifcs[i] = *ifc
		}
		return ifcs, nil
	}

	ifc, err := readInterface(ifindex - 1)
	if err != nil {
		return nil, err
	}
	return []Interface{*ifc}, nil
}

func readInterface(i int) (*Interface, error) {
	ifc := &Interface{
		Index: i + 1,                             // Offset the index by one to suit the contract
		Name:  netdir + "/ipifc/" + itoa.Itoa(i), // Name is the full path to the interface path in plan9
	}

	ifcstat := ifc.Name + "/status"
	ifcstatf, err := open(ifcstat)
	if err != nil {
		return nil, err
	}
	defer ifcstatf.close()

	line, ok := ifcstatf.readLine()
	if !ok {
		return nil, errors.New("invalid interface status file: " + ifcstat)
	}

	fields := getFields(line)
	if len(fields) < 4 {
		return nil, errors.New("invalid interface status file: " + ifcstat)
	}

	device := fields[1]
	mtustr := fields[3]

	mtu, _, ok := dtoi(mtustr)
	if !ok {
		return nil, errors.New("invalid status file of interface: " + ifcstat)
	}
	ifc.MTU = mtu

	// Not a loopback device ("/dev/null") or packet interface (e.g. "pkt2")
	if stringsHasPrefix(device, netdir+"/") {
		deviceaddrf, err := open(device + "/addr")
		if err != nil {
			return nil, err
		}
		defer deviceaddrf.close()

		line, ok = deviceaddrf.readLine()
		if !ok {
			return nil, errors.New("invalid address file for interface: " + device + "/addr")
		}

		if len(line) > 0 && len(line)%2 == 0 {
			ifc.HardwareAddr = make([]byte, len(line)/2)
			var ok bool
			for i := range ifc.HardwareAddr {
				j := (i + 1) * 2
				ifc.HardwareAddr[i], ok = xtoi2(line[i*2:j], 0)
				if !ok {
					ifc.HardwareAddr = ifc.HardwareAddr[:i]
					break
				}
			}
		}

		ifc.Flags = FlagUp | FlagRunning | FlagBroadcast | FlagMulticast
	} else {
		ifc.Flags = FlagUp | FlagRunning | FlagMulticast | FlagLoopback
	}

	return ifc, nil
}

func interfaceCount() (int, error) {
	d, err := os.Open(netdir + "/ipifc")
	if err != nil {
		return -1, err
	}
	defer d.Close()

	names, err := d.Readdirnames(0)
	if err != nil {
		return -1, err
	}

	// Assumes that numbered files in ipifc are strictly
	// the incrementing numbered directories for the
	// interfaces
	c := 0
	for _, name := range names {
		if _, _, ok := dtoi(name); !ok {
			continue
		}
		c++
	}

	return c, nil
}

// If the ifi is nil, interfaceAddrTable returns addresses for all
// network interfaces. Otherwise it returns addresses for a specific
// interface.
func interfaceAddrTable(ifi *Interface) ([]Addr, error) {
	var ifcs []Interface
	if ifi == nil {
		var err error
		ifcs, err = interfaceTable(0)
		if err != nil {
			return nil, err
		}
	} else {
		ifcs = []Interface{*ifi}
	}

	var addrs []Addr
	for _, ifc := range ifcs {
		status := ifc.Name + "/status"
		statusf, err := open(status)
		if err != nil {
			return nil, err
		}
		defer statusf.close()

		// Read but ignore first line as it only contains the table header.
		// See https://9p.io/magic/man2html/3/ip
		if _, ok := statusf.readLine(); !ok {
			return nil, errors.New("cannot read header line for interface: " + status)
		}

		for line, ok := statusf.readLine(); ok; line, ok = statusf.readLine() {
			fields := getFields(line)
			if len(fields) < 1 {
				return nil, errors.New("cannot parse IP address for interface: " + status)
			}
			addr := fields[0]
			ip := ParseIP(addr)
			if ip == nil {
				return nil, errors.New("cannot parse IP address for interface: " + status)
			}

			// The mask is represented as CIDR relative to the IPv6 address.
			// Plan 9 internal representation is always IPv6.
			maskfld := fields[1]
			maskfld = maskfld[1:]
			pfxlen, _, ok := dtoi(maskfld)
			if !ok {
				return nil, errors.New("cannot parse network mask for interface: " + status)
			}
			var mask IPMask
			if ip.To4() != nil { // IPv4 or IPv6 IPv4-mapped address
				mask = CIDRMask(pfxlen-8*len(v4InV6Prefix), 8*IPv4len)
			}
			if ip.To16() != nil && ip.To4() == nil { // IPv6 address
				mask = CIDRMask(pfxlen, 8*IPv6len)
			}

			addrs = append(addrs, &IPNet{IP: ip, Mask: mask})
		}
	}

	return addrs, nil
}

// interfaceMulticastAddrTable returns addresses for a specific
// interface.
func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) {
	return nil, nil
}
