package main

import (
	"bufio"
	"context"
	"flag"
	"fmt"
	"io"
	"net"
	"os"
	"sort"
	"strings"
	"time"

	"github.com/golang/glog"

	mirko "code.hackerspace.pl/hscloud/go/mirko"
	hpb "code.hackerspace.pl/hscloud/hswaw/proto"
)

type lease struct {
	hardware net.HardwareAddr
	ip       net.IP
	from     time.Time
	to       time.Time
}

const timeFmt = "2006/01/02 15:04:05"

func parseLeases(f io.Reader, now time.Time) ([]lease, error) {
	scanner := bufio.NewScanner(f)

	leases := make(map[string]*lease)

	var curAddr *net.IP
	var curStart *time.Time
	var curEnd *time.Time
	var curHW *net.HardwareAddr

	for scanner.Scan() {
		l := scanner.Text()
		l = strings.TrimSpace(l)
		if len(l) < 1 {
			continue
		}

		if strings.HasPrefix(l, "#") {
			continue
		}

		parts := strings.Fields(l)
		if len(parts) < 1 {
			continue
		}

		if curAddr == nil {
			switch parts[0] {
			case "lease":
				if len(parts) < 3 || parts[2] != "{" {
					glog.Warningf("invalid lease line %q", l)
					break
				}

				ip := net.ParseIP(parts[1])
				if ip == nil {
					glog.Warningf("invalid lease line %q: invalid ip")
					break
				}
				curAddr = &ip
			}
		} else {
			parts[len(parts)-1] = strings.TrimRight(parts[len(parts)-1], ";")

			switch parts[0] {
			case "starts":
				fallthrough
			case "ends":
				if len(parts) != 4 {
					glog.Warningf("invalid time line %q", l)
					break
				}
				t, err := time.Parse(timeFmt, fmt.Sprintf("%s %s", parts[2], parts[3]))
				if err != nil {
					glog.Warningf("invalid time line %q: %v", l, err)
					break
				}
				if parts[0] == "starts" {
					curStart = &t
				} else {
					curEnd = &t
				}
			case "hardware":
				if len(parts) < 2 {
					glog.Warningf("invalid hardware line %q", l)
					break
				}
				if parts[1] != "ethernet" {
					break
				}
				if len(parts) != 3 {
					glog.Warningf("invalid hardware ethernet line %q", l)
					break
				}
				hw, err := net.ParseMAC(parts[2])
				if err != nil {
					glog.Warningf("invalid hardware ethernet line %q: %v", l, err)
					break
				}
				curHW = &hw
			case "}":
				if curStart == nil || curEnd == nil || curHW == nil {
					glog.V(2).Info("Invalid block for %q, not enough fields", curAddr.String())
				} else if curEnd.Before(now) {
					// skip.
				} else {
					leases[curHW.String()] = &lease{
						hardware: *curHW,
						ip:       *curAddr,
						from:     *curStart,
						to:       *curEnd,
					}
				}
				curAddr = nil
				curStart = nil
				curEnd = nil
				curHW = nil
			}
		}
	}

	ret := make([]lease, len(leases))
	i := 0
	for _, v := range leases {
		ret[i] = *v
		i += 1
	}

	return ret, nil
}

type service struct {
	leaseFile          string
	leaseRefreshString string
	leaseRefresh       time.Duration
	leaseC             chan chan []lease
}

func (s *service) work(ctx context.Context) {
	leases := []lease{}

	ticker := time.NewTicker(s.leaseRefresh)
	start := make(chan struct{}, 1)
	start <- struct{}{}

	work := func() {
		glog.Infof("Parsing leases...")
		f, err := os.Open(s.leaseFile)
		if err != nil {
			glog.Errorf("Could not open lease file: %v", err)
			return
		}
		l, err := parseLeases(f, time.Now())
		f.Close()
		if err != nil {
			glog.Errorf("Could not parse lease file: %v", err)
			return
		}
		sort.Slice(l, func(i, j int) bool { return string([]byte(l[i].ip)) < string([]byte(l[j].ip)) })
		leases = l
		glog.Infof("Got %d leases", len(leases))
	}

	glog.Infof("Worker started.")

	for {
		select {
		case <-start:
			work()
		case <-ticker.C:
			work()
		case c := <-s.leaseC:
			c <- leases
		case <-ctx.Done():
			glog.Infof("Worker quitting.")
			close(start)
			return
		}
	}
}

func (s *service) Leases(ctx context.Context, req *hpb.LeasifierLeasesRequest) (*hpb.LeasifierLeasesResponse, error) {
	c := make(chan []lease)
	s.leaseC <- c
	leases := <-c

	res := &hpb.LeasifierLeasesResponse{
		Leases: make([]*hpb.LeasifierLease, len(leases)),
	}

	for i, l := range leases {
		res.Leases[i] = &hpb.LeasifierLease{
			PhysicalAddress: l.hardware.String(),
			IpAddress:       l.ip.String(),
		}
	}

	return res, nil
}

func main() {
	s := &service{
		leaseC: make(chan chan []lease),
	}

	flag.StringVar(&s.leaseFile, "lease_file", "/var/db/dhcpd.leases", "Location of leasefile")
	flag.StringVar(&s.leaseRefreshString, "lease_refresh", "1m", "How often to refresh leases")
	flag.Parse()

	d, err := time.ParseDuration(s.leaseRefreshString)
	if err != nil {
		glog.Exit(err)
	}
	s.leaseRefresh = d

	m := mirko.New()
	if err := m.Listen(); err != nil {
		glog.Exitf("Could not listen: %v", err)
	}

	hpb.RegisterLeasifierServer(m.GRPC(), s)

	s.setupStatusz(m)
	go s.work(m.Context())

	if err := m.Serve(); err != nil {
		glog.Exitf("Could not run: %v", err)
	}

	glog.Info("Running.")
	<-m.Done()

}
