package ethernet

import (
	"fmt"
	"net"
	"time"
)

// EthAddr implements net.Addr
type EthAddr struct {
	address string
}

// String returns the address
func (ea EthAddr) String() string {
	return ea.address
}

// Network returns "ethernet"
func (ea EthAddr) Network() string {
	return "ethernet"
}

// Conn is a wrapper that implements net.Conn and sents packets to a particular destination (write only)
type Conn struct {
	eth      *EthernetInterface
	destAddr MACAddr
}

// NewConn creates a new ethernet conn
func (e *EthernetInterface) NewConn(dest MACAddr) net.Conn {
	return &Conn{
		eth:      e,
		destAddr: dest,
	}
}

// Read is there to fulfill the net.Conn interface
func (c *Conn) Read(b []byte) (n int, err error) {
	return 0, fmt.Errorf("not supported")
}

// Write sends b on the Conn
func (c *Conn) Write(b []byte) (n int, err error) {
	err = c.eth.SendPacket(c.destAddr, b)
	if err != nil {
		return 0, err
	}

	return len(b), nil
}

// Close is here to fulfill the net.Conn interface
func (c *Conn) Close() error {
	return fmt.Errorf("not supported")
}

// LocalAddr returns the local address
func (c *Conn) LocalAddr() net.Addr {
	return EthAddr{}
}

// RemoteAddr returns the remote address
func (c *Conn) RemoteAddr() net.Addr {
	return EthAddr{}
}

// SetDeadline is here to fulfill the net.Conn interface
func (c *Conn) SetDeadline(t time.Time) error {
	return fmt.Errorf("not supported")
}

// SetReadDeadline is here to fulfill the net.Conn interface
func (c *Conn) SetReadDeadline(t time.Time) error {
	return fmt.Errorf("not supported")
}

// SetWriteDeadline is here to fulfill the net.Conn interface
func (c *Conn) SetWriteDeadline(t time.Time) error {
	return fmt.Errorf("not supported")
}
