package main

import (
	"context"
	"flag"
	"net"
	"net/http"

	"code.hackerspace.pl/q3k/hspki"
	"github.com/golang/glog"
	"github.com/q3k/statusz"
	"github.com/ziutek/telnet"
	"golang.org/x/net/trace"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/reflection"
	"google.golang.org/grpc/status"

	pb "code.hackerspace.pl/q3k/m6220-proxy/proto"
)

var (
	flagListenAddress  string
	flagDebugAddress   string
	flagSwitchAddress  string
	flagSwitchUsername string
	flagSwitchPassword string
)

func init() {
	flag.Set("logtostderr", "true")
}

type service struct {
	connectionSemaphore chan int
}

func (s *service) connect() (*cliClient, error) {
	s.connectionSemaphore <- 1
	conn, err := telnet.Dial("tcp", flagSwitchAddress)
	if err != nil {
		<-s.connectionSemaphore
		return nil, err
	}

	cli := newCliClient(conn, flagSwitchUsername, flagSwitchPassword)
	return cli, nil
}

func (s *service) disconnect() {
	<-s.connectionSemaphore
}

func (s *service) RunCommand(ctx context.Context, req *pb.RunCommandRequest) (*pb.RunCommandResponse, error) {
	if req.Command == "" {
		return nil, status.Error(codes.InvalidArgument, "command cannot be null")
	}

	cli, err := s.connect()
	if err != nil {
		return nil, status.Error(codes.Unavailable, "could not connect to backend")
	}
	defer s.disconnect()

	lines, effective, err := cli.runCommand(ctx, req.Command)
	if err != nil {
		return nil, err
	}
	res := &pb.RunCommandResponse{
		EffectiveCommand: effective,
		Lines:            lines,
	}
	return res, nil
}

func main() {
	flag.StringVar(&flagListenAddress, "listen_address", "127.0.0.1:42000", "Address to listen on for gRPC")
	flag.StringVar(&flagDebugAddress, "debug_address", "127.0.0.1:42001", "Address to listen on for Debug HTTP")
	flag.StringVar(&flagSwitchAddress, "switch_address", "127.0.0.1:23", "Telnet address of M6220")
	flag.StringVar(&flagSwitchUsername, "switch_username", "admin", "Switch login username")
	flag.StringVar(&flagSwitchPassword, "switch_password", "admin", "Switch login password")
	flag.Parse()

	s := &service{
		connectionSemaphore: make(chan int, 1),
	}

	grpc.EnableTracing = true
	grpcLis, err := net.Listen("tcp", flagListenAddress)
	if err != nil {
		glog.Exitf("Could not listen on %v: %v", flagListenAddress, err)
	}
	grpcSrv := grpc.NewServer(hspki.WithServerHSPKI()...)
	pb.RegisterM6220ProxyServer(grpcSrv, s)
	reflection.Register(grpcSrv)

	glog.Infof("Starting gRPC on %v", flagListenAddress)
	go func() {
		if err := grpcSrv.Serve(grpcLis); err != nil {
			glog.Exitf("Could not start gRPC: %v", err)
		}
	}()

	if flagDebugAddress != "" {
		glog.Infof("Starting debug on %v", flagDebugAddress)
		httpMux := http.NewServeMux()
		httpMux.HandleFunc("/debug/status", statusz.StatusHandler)
		httpMux.HandleFunc("/debug/requests", trace.Traces)
		httpMux.HandleFunc("/", statusz.StatusHandler)

		httpLis, err := net.Listen("tcp", flagDebugAddress)
		if err != nil {
			glog.Exitf("Could not listen on %v: %v", flagDebugAddress, err)
		}
		httpSrv := &http.Server{
			Addr:    flagDebugAddress,
			Handler: httpMux,
		}

		go func() {
			if err := httpSrv.Serve(httpLis); err != nil {
				glog.Exitf("Could not start HTTP server: %v", err)
			}
		}()

	}

	glog.Infof("Running!")

	select {}
}
