package main

import (
	"context"
	"flag"
	"fmt"
	"reflect"
	"strconv"
	"strings"

	"code.hackerspace.pl/hscloud/go/mirko"
	"github.com/golang/glog"
	"github.com/ziutek/telnet"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"

	pb "code.hackerspace.pl/hscloud/dc/m6220-proxy/proto"
	dpb "code.hackerspace.pl/hscloud/dc/proto"
)

var (
	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 switch")
	}
	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 (s *service) parseInterfaceStatus(res *dpb.GetPortsResponse, lines []string) error {
	if len(lines) < 4 {
		return fmt.Errorf("need at least 4 lines of output, got %d", len(lines))
	}
	if lines[0] != "" {
		return fmt.Errorf("expected first line to be empty, is %q", lines[0])
	}
	header1parts := strings.Fields(lines[1])
	if want := []string{"Port", "Description", "Duplex", "Speed", "Neg", "Link", "Flow", "Control"}; !reflect.DeepEqual(want, header1parts) {
		return fmt.Errorf("expected header1 to be %v, got %v", want, header1parts)
	}

	header2parts := strings.Fields(lines[2])
	if want := []string{"State", "Status"}; !reflect.DeepEqual(want, header2parts) {
		return fmt.Errorf("expected header2 to be %v, got %v", want, header2parts)
	}

	if lines[3][0] != '-' {
		return fmt.Errorf("expected header3 to start with -, got %q", lines[3])
	}

	for _, line := range lines[4:] {
		parts := strings.Fields(line)
		if len(parts) < 6 {
			break
		}
		portName := parts[0]
		if strings.HasPrefix(portName, "Gi") && strings.HasPrefix(portName, "Ti") {
			break
		}

		speedStr := parts[len(parts)-4]
		stateStr := parts[len(parts)-2]

		port := &dpb.SwitchPort{
			Name: portName,
		}
		if speedStr == "100" {
			port.Speed = dpb.SwitchPort_SPEED_100M
		} else if speedStr == "1000" {
			port.Speed = dpb.SwitchPort_SPEED_1G
		} else if speedStr == "10000" {
			port.Speed = dpb.SwitchPort_SPEED_10G
		}
		if stateStr == "Up" {
			port.LinkState = dpb.SwitchPort_LINKSTATE_UP
		} else if stateStr == "Down" {
			port.LinkState = dpb.SwitchPort_LINKSTATE_DOWN
		}

		res.Ports = append(res.Ports, port)
	}

	return nil
}

func (s *service) parseInterfaceConfig(port *dpb.SwitchPort, lines []string) error {
	glog.Infof("%+v", port)
	for _, line := range lines {
		glog.Infof("%s: %q", port.Name, line)
		parts := strings.Fields(line)
		if len(parts) < 1 {
			continue
		}

		if len(parts) >= 2 && parts[0] == "switchport" {
			if parts[1] == "mode" {
				if port.PortMode != dpb.SwitchPort_PORTMODE_INVALID {
					return fmt.Errorf("redefinition of switchport mode")
				}
				if parts[2] == "access" {
					port.PortMode = dpb.SwitchPort_PORTMODE_SWITCHPORT_UNTAGGED
				} else if parts[2] == "trunk" {
					port.PortMode = dpb.SwitchPort_PORTMODE_SWITCHPORT_TAGGED
				} else if parts[2] == "general" {
					port.PortMode = dpb.SwitchPort_PORTMODE_SWITCHPORT_GENERIC
				} else {
					port.PortMode = dpb.SwitchPort_PORTMODE_MANGLED
				}
			}

			if parts[1] == "access" {
				if port.PortMode == dpb.SwitchPort_PORTMODE_INVALID {
					port.PortMode = dpb.SwitchPort_PORTMODE_SWITCHPORT_UNTAGGED
				}
				if len(parts) > 3 && parts[2] == "vlan" {
					vlan, err := strconv.Atoi(parts[3])
					if err != nil {
						return fmt.Errorf("invalid vlan: %q", parts[3])
					}
					port.VlanNative = int32(vlan)
				}
			}

			if parts[1] == "trunk" {
				if len(parts) >= 5 && parts[2] == "allowed" && parts[3] == "vlan" {
					vlans := strings.Split(parts[4], ",")
					for _, vlan := range vlans {
						vlanNum, err := strconv.Atoi(vlan)
						if err != nil {
							return fmt.Errorf("invalid vlan: %q", parts[3])
						}
						port.VlanTagged = append(port.VlanTagged, int32(vlanNum))
					}
				}
			}
		} else if len(parts) >= 2 && parts[0] == "mtu" {
			mtu, err := strconv.Atoi(parts[1])
			if err != nil {
				return fmt.Errorf("invalid mtu: %q", parts[3])
			}
			port.Mtu = int32(mtu)
		} else if len(parts) >= 2 && parts[0] == "spanning-tree" && parts[1] == "portfast" {
			port.SpanningTreeMode = dpb.SwitchPort_SPANNING_TREE_MODE_PORTFAST
		}
	}

	// no mode -> access
	if port.PortMode == dpb.SwitchPort_PORTMODE_INVALID {
		port.PortMode = dpb.SwitchPort_PORTMODE_SWITCHPORT_UNTAGGED
	}

	// apply defaults
	if port.Mtu == 0 {
		port.Mtu = 1500
	}
	if port.SpanningTreeMode == dpb.SwitchPort_SPANNING_TREE_MODE_INVALID {
		port.SpanningTreeMode = dpb.SwitchPort_SPANNING_TREE_MODE_AUTO_PORTFAST
	}

	// sanitize
	if port.PortMode == dpb.SwitchPort_PORTMODE_SWITCHPORT_UNTAGGED {
		port.VlanTagged = []int32{}
		port.Prefixes = []string{}
		if port.VlanNative == 0 {
			port.VlanNative = 1
		}
	} else if port.PortMode == dpb.SwitchPort_PORTMODE_SWITCHPORT_TAGGED {
		port.VlanNative = 0
		port.Prefixes = []string{}
	} else if port.PortMode == dpb.SwitchPort_PORTMODE_SWITCHPORT_GENERIC {
		port.Prefixes = []string{}
		if port.VlanNative == 0 {
			port.VlanNative = 1
		}
	}
	return nil
}

func (s *service) GetPorts(ctx context.Context, req *dpb.GetPortsRequest) (*dpb.GetPortsResponse, error) {
	cli, err := s.connect()
	if err != nil {
		return nil, status.Error(codes.Unavailable, "could not connect to switch")
	}
	defer s.disconnect()
	res := &dpb.GetPortsResponse{}

	statusLines, _, err := cli.runCommand(ctx, "show interface status")
	if err != nil {
		return nil, status.Error(codes.Unavailable, "could not get interface status from switch")
	}

	err = s.parseInterfaceStatus(res, statusLines)
	if err != nil {
		return nil, status.Errorf(codes.Unavailable, "could not parse interface status from switch: %v", err)
	}

	for _, port := range res.Ports {
		configLines, _, err := cli.runCommand(ctx, "show run interface "+port.Name)
		if err != nil {
			return nil, status.Error(codes.Unavailable, "could not get interface config from switch")
		}
		err = s.parseInterfaceConfig(port, configLines)
		if err != nil {
			return nil, status.Errorf(codes.Unavailable, "could not parse interface config from switch: %v", err)
		}
	}

	return res, nil
}

func main() {
	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),
	}

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

	pb.RegisterM6220ProxyServer(m.GRPC(), s)
	dpb.RegisterSwitchControlServer(m.GRPC(), s)

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

	select {}
}
