// inspired from:
// https://github.com/mactsouk/opensource.com.git
// and
// https://coderwall.com/p/wohavg/creating-a-simple-tcp-server-in-go

package dnssecsocket

import "os"
import "bufio"
import "math/rand"
import "net"
import "strconv"
import "strings"
import log "github.com/sirupsen/logrus"
// import "github.com/wercker/journalhook"

import "git.wit.com/wit/shell"

// will try to get this hosts FQDN
// import "github.com/Showmax/go-fqdn"

import "github.com/miekg/dns"

// import "github.com/davecgh/go-spew/spew"

const MIN = 1
const MAX = 100

func random() int {
	return rand.Intn(MAX-MIN) + MIN
}

func GetRemoteAddr(conn net.TCPConn) string {
	clientAddr := conn.RemoteAddr().String()
	parts := strings.Split(clientAddr, "]")
	ipv6 := parts[0]
	return ipv6[1:]
}

//
// Handle each connection
// Each client must send it's hostname as the first line
// Then each hostname is verified with DNSSEC
//
func HandleConnection(conn *net.TCPConn) {
	// Disable journalhook until it builds on Windows
	// journalhook.Enable()

	// spew.Dump(conn)
	// ipv6client := GetRemoteAddr(c)
	ipv6client := conn.RemoteAddr()
	log.Println("Serving to %s as the IPv6 client", ipv6client)

	// setup this TCP socket as the "standard input"
	// newStdin, _ := bufio.NewReader(conn.File())
	newStdin, _ := conn.File()
	newreader := bufio.NewReader(newStdin)

	log.Println("Waiting for the client to tell me its name")
	netData, err := newreader.ReadString('\n')
	if err != nil {
		log.Println(err)
		return
	}
	clientHostname := strings.TrimSpace(netData)
	log.Println("Recieved client hostname as:", clientHostname)

	dnsRR := Dnstrace(clientHostname, "AAAA")
	if (dnsRR == nil) {
		log.Println("dnsRR IS NIL")
		log.Println("dnsRR IS NIL")
		log.Println("dnsRR IS NIL")
		conn.Close()
		return
	}
	ipaddr := dns.Field(dnsRR, 1)
	log.Println("Client claims to be:   ", ipaddr)
	log.Println("Serving to IPv6 client:", ipv6client)

/* TODO: figure out how to fix this check
	if (ipaddr != ipv6client) {
		log.Println()
		log.Println("DNSSEC ERROR: client IPv6 does not work")
		log.Println("DNSSEC ERROR: client IPv6 does not work")
		log.Println("DNSSEC ERROR: client IPv6 does not work")
		log.Println()
		conn.Close()
		return
	}
*/

	f, _ := conn.File()
//	shell.SetStdout(f)
//	shell.SpewOn()		// turn this on if you want to look at the process exit states

	// send all log() output to systemd journalctl
//	shell.UseJournalctl()

	for {
		defer shell.SetStdout(os.Stdout)
		defer conn.Close()
		netData, err := newreader.ReadString('\n')
		if err != nil {
			log.Println(err)
			return
		}

		temp := strings.TrimSpace(string(netData))
		if temp == "STOP" {
			break
		}
		log.Println("Recieved: ", temp)

		if (temp == "list") {
			log.Println("Should run list here")
			shell.SetStdout(f)
			shell.Run("/root/bin/list.testing.com")
			shell.SetStdout(os.Stdout)
		}

		if (temp == "cpuinfo") {
			log.Println("Should cat /proc/cpuinfo")
			shell.SetStdout(f)
			shell.Run("cat /proc/cpuinfo")
			shell.SetStdout(os.Stdout)
		}

		result := strconv.Itoa(random()) + "\n"
		conn.Write([]byte(string(result)))
	}
}