package auth

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"errors"
	"net"

	"git.loafle.net/commons_go/util/net/gateway"
	"git.loafle.net/overflow/overflow_probes/central/api/module"
	"git.loafle.net/overflow/overflow_probes/config"
	"github.com/shirou/gopsutil/host"
)

func getRegistHeader() (string, error) {
	var err error
	nap := module.NoAuthProbe{
		APIKey: config.Config.Domain.APIKey,
	}
	var nad *module.NoAuthProbeDescription
	if nad, err = getDescription(); nil != err {
		return "", err
	}

	var buf []byte
	if buf, err = json.Marshal(nad); nil != err {
		return "", err
	}
	nap.Description = string(buf)

	if buf, err = json.Marshal(nap); nil != err {
		return "", err
	}

	enc := base64.StdEncoding.EncodeToString(buf)

	return enc, nil
}

func getDescription() (*module.NoAuthProbeDescription, error) {
	nad := &module.NoAuthProbeDescription{}

	if err := getHost(&nad.Host); nil != err {
		return nil, err
	}

	if err := getNetwork(&nad.Network); nil != err {
		return nil, err
	}

	return nad, nil
}

func getHost(h *module.NoAuthProbeDescriptionHost) error {
	if i, err := host.Info(); nil == err {
		h.Name = i.Hostname
		h.OS = i.OS
		h.Platform = i.Platform
		h.PlatformFamily = i.PlatformFamily
		h.KernelVersion = i.KernelVersion
		h.HostID = i.HostID
	} else {
		return err
	}

	return nil
}

func getNetwork(n *module.NoAuthProbeDescriptionNetwork) error {
	var ip net.IP
	var iface string
	var err error
	if ip, iface, err = gateway.DiscoverGateway(); nil != err {
		return err
	}

	interfaces, err := net.Interfaces()
	if err != nil {
		return err
	}

	idx := -1

	for _idx, i := range interfaces {
		if i.Name == iface {
			idx = _idx
			break
		}
	}

	if -1 == idx {
		return errors.New("Interface of gateway is not exist")
	}

	i := interfaces[idx]

	n.Name = i.Name
	n.MacAddress = i.HardwareAddr.String()
	n.Gateway = ip.String()

	if addrs, err := i.Addrs(); nil == err {
		var buffer bytes.Buffer
		for _idx, a := range addrs {
			if 0 < _idx {
				buffer.WriteString("|")
			}
			buffer.WriteString(a.String())
		}
		n.Address = buffer.String()
	} else {
		return err
	}

	return nil
}
