package info

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

	"git.loafle.net/commons/util-go/net/gateway"
	noauthprobeM "git.loafle.net/overflow/commons-go/model/noauthprobe"
	"github.com/shirou/gopsutil/host"
)

func GetRegistHeader(apiKey string) (string, error) {
	var err error
	nap := noauthprobeM.NoAuthProbe{
		APIKey: apiKey,
	}

	var napd *noauthprobeM.NoAuthProbeDescription
	if napd, err = getDescription(); nil != err {
		return "", err
	}

	var buf []byte
	if buf, err = json.Marshal(napd); 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() (*noauthprobeM.NoAuthProbeDescription, error) {
	var err error
	napd := &noauthprobeM.NoAuthProbeDescription{}

	if napd.Host, err = getHost(); nil != err {
		return nil, err
	}

	if napd.Network, err = getNetwork(); nil != err {
		return nil, err
	}

	return napd, nil
}

func getHost() (*noauthprobeM.NoAuthProbeDescriptionHost, error) {
	if i, err := host.Info(); nil == err {
		h := &noauthprobeM.NoAuthProbeDescriptionHost{}

		h.Name = i.Hostname
		h.OS = i.OS
		h.Platform = i.Platform
		h.PlatformFamily = i.PlatformFamily
		h.KernelVersion = i.KernelVersion
		h.HostID = i.HostID

		return h, nil
	} else {
		return nil, err
	}
}

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

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

	idx := -1

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

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

	n := &noauthprobeM.NoAuthProbeDescriptionNetwork{}

	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 nil, err
	}

	return n, nil
}
