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"

	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.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)
	}

	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)
	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", "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
		CurrentNote string
		CurrentDeadline string
		SampleName string
	}{
		You: cur.addr == remoteAddr(r),
		CurrentAddress: cur.addr,
		CurrentNote: 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, "sorry, 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)
}
