package main

import (
	"git.xeserv.us/xena/route/internal/elfs"
	proto "git.xeserv.us/xena/route/proto"
	"github.com/Xe/ln"
	"golang.org/x/net/context"
)

// Route implements rout.RoutesServer for gRPC
type Route struct {
	*Server
}

// interface assertions
var (
	_ proto.Routes = &Route{}
)

// Get fetches a route from the database.
func (r *Route) Get(ctx context.Context, req *proto.GetRouteRequest) (*proto.Route, error) {
	clitok, err := r.getAuth(ctx, "get single route", "route:get")
	if err != nil {
		return nil, handleError(ctx, clitok, err, ln.F{"action": "Route.Get_getAuth"})
	}

	val, err := r.db.GetRoute(ctx, req.Id)
	if err != nil {
		return nil, handleError(ctx, clitok, err, ln.F{"action": "get single route from database", "id": req.Id})
	}

	if val.Creator != clitok.Owner {
		return nil, handleError(ctx, clitok, ErrNotAuthorized, ln.F{"action": "Route.Get_wrong_ownership"})
	}

	return val.AsProto(), nil
}

// GetAll fetches all of the routes that you own.
func (r *Route) GetAll(ctx context.Context, req *proto.Nil) (*proto.GetAllRoutesResponse, error) {
	clitok, err := r.getAuth(ctx, "get all routes for user", "route:getall")
	if err != nil {
		return nil, handleError(ctx, clitok, err, ln.F{"action": "Route.GetAll_getAuth"})
	}

	routes, err := r.db.GetAllRoutes(ctx, clitok.Owner)
	if err != nil {
		return nil, handleError(ctx, clitok, err, ln.F{"action": "get all routes for user from database"})
	}

	result := []*proto.Route{}

	// let result = apply routeAsProto routes
	for _, rt := range routes {
		result = append(result, rt.AsProto())
	}

	return &proto.GetAllRoutesResponse{
		Routes: result,
	}, nil
}

func (r *Route) Put(ctx context.Context, rt *proto.Route) (*proto.Route, error) {
	clitok, err := r.getAuth(ctx, "put new route", "route:put")
	if err != nil {
		return nil, handleError(ctx, clitok, err, ln.F{"action": "Route.Put_getAuth"})
	}

	if rt.Host == "" {
		rt.Host = elfs.MakeName() + r.cfg.DomainSuffix
	}

	drt, err := r.db.PutRoute(ctx, rt.Host, clitok.Owner)
	if err != nil {
		return nil, handleError(ctx, clitok, err, ln.F{"action": "put route to database"})
	}

	ln.Log(ctx, drt, ln.Action("created new route"))

	return drt.AsProto(), nil
}

func (r *Route) Delete(ctx context.Context, rt *proto.Route) (*proto.Nil, error) {
	clitok, err := r.getAuth(ctx, "delete single route", "route:delete")
	if err != nil {
		return nil, handleError(ctx, clitok, err, ln.F{"action": "Route.Delete_getAuth"})
	}

	drt, err := r.db.GetRoute(ctx, rt.Host)
	if err != nil {
		return nil, handleError(ctx, clitok, err, ln.F{"action": "fetch route from database", "host": rt.Host})
	}

	if drt.Creator != clitok.Owner {
		return nil, handleError(ctx, clitok, ErrNotAuthorized, ln.F{"action": "user not authorized to delete this route", "host": rt.Host})
	}

	err = r.db.DeleteRoute(ctx, rt.Id)
	f := drt.F()
	f["action"] = "delete route from database"
	if err != nil {
		handleError(ctx, clitok, ErrNotAuthorized, f)
	}

	f["action"] = "deleted route from database"
	ln.Log(ctx, f, drt)

	return &proto.Nil{}, nil
}
