package main

import (
	"context"
	"flag"
	"fmt"
	"html/template"
	"net"
	"net/http"
	"math/rand"
	"strings"
	"time"

	"github.com/golang/glog"

	mirko "code.hackerspace.pl/hscloud/go/mirko"
	"code.hackerspace.pl/hscloud/hswaw/laserproxy/tpl"
)

var (
	flagLaserAddress = "10.11.0.10"
	flagLaserNetworkAddress = "10.11.0.1"
	flagClientNetworkAddress = "10.8.1.2"
	flagWebAddress = "127.0.0.1:8080"
	flagOwnershipDuration = "1h"

	tplIndex = template.Must(template.New("index.html").Parse(tpl.MustAssetString("index.html")))
)

type service struct {
	lockCtrl chan *lockCtrl
}

func main() {
	flag.StringVar(&flagLaserAddress, "laser_address", flagLaserAddress, "Address of Ruida controller on laser network")
	flag.StringVar(&flagLaserNetworkAddress, "laser_network", flagLaserNetworkAddress, "Address of proxy on laser network")
	flag.StringVar(&flagClientNetworkAddress, "client_network", flagClientNetworkAddress, "Address of proxy on client network")
	flag.StringVar(&flagWebAddress, "web_address", flagWebAddress, "Address and port to listen on for public web connections")
	flag.StringVar(&flagOwnershipDuration, "timeout_duration", flagOwnershipDuration, "Time after which lasercutter lock will expire when not in use")

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

	lisLaser, err := net.ListenPacket("udp", fmt.Sprintf("%s:40200", flagLaserNetworkAddress))
	if err != nil {
		glog.Fatalf("could not listen on laser network: %v", err)
	}
	defer lisLaser.Close()

	lisClient, err := net.ListenPacket("udp", fmt.Sprintf("%s:50200", flagClientNetworkAddress))
	if err != nil {
		glog.Fatalf("could not listen on client network: %v", err)
	}
	defer lisClient.Close()

	laserIP := net.ParseIP(flagLaserAddress)
	if laserIP == nil {
		glog.Fatalf("could not parse laser IP address %q", flagLaserAddress)
	}
	laserAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:50200", laserIP.String()))
	if err != nil {
		glog.Fatalf("could not make laser UDP address: %v", err)
	}

	ownershipDuration, err := time.ParseDuration(flagOwnershipDuration)
	if err != nil {
		glog.Fatalf("could not parse timeout duration: %v", err)
	}

	ctx := m.Context()
	s := &service{
		lockCtrl: make(chan *lockCtrl),
	}
	updates := make(chan *lockUpdate)
	go s.runProxy(ctx, updates, laserAddr, lisLaser, lisClient)
	go s.runLocker(ctx, s.lockCtrl, ownershipDuration)
	s.lockCtrl <- &lockCtrl{
		subscribe: &lockCtrlSubscribe{
			subscriber: updates,
		},
	}

	mux := http.NewServeMux()
	mux.HandleFunc("/", s.handlerIndex)
	mux.HandleFunc("/take", s.handlerTake)
	mux.HandleFunc("/release", s.handlerRelease)
	mux.HandleFunc("/force", s.handlerForce)
	httpSrv := &http.Server{Addr: flagWebAddress, Handler: mux}

	glog.Infof("Listening for web connections on %q...", flagWebAddress)
	go func() {
		if err := httpSrv.ListenAndServe(); err != nil {
			glog.Error(err)
		}
	}()

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

	glog.Info("Running.")
	<-m.Done()
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	httpSrv.Shutdown(ctx)
}

var (
	sampleNames = []string{
		"enleth", "radex", "qdot", "hans acker", "lars aser", "makłowicz",
	}
)

func remoteAddr(r *http.Request) string {
	if fwd := r.Header.Get("X-Forwarded-For"); fwd != "" {
		return strings.Split(fwd, ":")[0]
	}
	return strings.Split(r.RemoteAddr, ":")[0]
}

func (s *service) handlerIndex(w http.ResponseWriter, r *http.Request) {
	res := make(chan *lockResCurrent)
	s.lockCtrl <- &lockCtrl{
		getCurrent: &lockCtrlGetCurrent{
			res: res,
		},
	}
	cur := <-res

	err := tplIndex.Execute(w, struct {
		You bool
		CurrentAddress string
		CurrentName string
		CurrentDeadline string
		SampleName string
	}{
		You: cur.addr == remoteAddr(r),
		CurrentAddress: cur.addr,
		CurrentName: cur.note,
		CurrentDeadline: fmt.Sprintf("%d minute(s)", int(cur.deadline.Sub(time.Now()).Minutes())),
		SampleName: sampleNames[rand.Intn(len(sampleNames))],
	})
	if err != nil {
		glog.Errorf("rendering template: %v", err)
	}
}

func (s *service) handlerTake(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		return
	}
	r.ParseForm()
	who := r.Form.Get("who")
	prev := r.Form.Get("prev")
	if who == "" {
		fmt.Fprintf(w, "excuse me, who are you? please specify a name")
		return
	}

	res := make(chan bool)
	take := &lockCtrlTake{
		note: who,
		addr: remoteAddr(r),
		prev: prev,
		res: res,
	}
	s.lockCtrl <- &lockCtrl{
		take: take,
	}
	won := <-res

	if won {
		http.Redirect(w, r, "/", 302)
	} else {
		fmt.Fprintf(w, "lock not taken")
	}
}

func (s *service) handlerRelease(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		return
	}
	res := make(chan struct{})
	s.lockCtrl <- &lockCtrl{
		release: &lockCtrlRelease{
			addr: remoteAddr(r),
			res: res,
		},
	}
	<-res

	http.Redirect(w, r, "/", 302)
}

func (s *service) handlerForce(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		return
	}
	res := make(chan struct{})
	s.lockCtrl <- &lockCtrl{
		release: &lockCtrlRelease{
			force: true,
			res: res,
		},
	}
	<-res

	http.Redirect(w, r, "/", 302)
}
