package main

import (
	"fmt"
	"log"

	"github.com/labstack/echo"
)

type Logger interface {
	WithField(key string, value interface{}) Logger
}

type controllerAdder struct {
	Logger Logger
	Ctx    *Context
}

type cGet interface {
	GET(c echo.Context) error
}
type cPost interface {
	POST(c echo.Context) error
}
type cPut interface {
	PUT(c echo.Context) error
}
type cDelete interface {
	DELETE(c echo.Context) error
}

type controller interface {
	SetBaseCtrl(base *BaseController)
}

type EchoOrGroup interface {
	GET(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc)
	POST(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc)
	PUT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc)
	DELETE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc)
}

func (c *controllerAdder) AddPaths(paths []string, e EchoOrGroup, ctrl controller, mware ...echo.MiddlewareFunc) {
	baseCtrl := getNewBaseController(c.Ctx, c.Logger.WithField("controller", fmt.Sprintf("%T", c)))
	ctrl.SetBaseCtrl(baseCtrl)

	cnt := 0
	for _, path := range paths {
		if get, ok := ctrl.(cGet); ok {
			cnt++
			e.GET(path, get.GET, mware...)
		}
		if post, ok := ctrl.(cPost); ok {
			cnt++
			e.POST(path, post.POST, mware...)
		}
		if put, ok := ctrl.(cPut); ok {
			cnt++
			e.PUT(path, put.PUT, mware...)
		}
		if del, ok := ctrl.(cDelete); ok {
			cnt++
			e.DELETE(path, del.DELETE, mware...)
		}
	}
	if cnt == 0 {
		log.Fatalf("No controller methods found to register for controller %T", c)
	}
}

func RegisterRouters(ctrlAdder *controllerAdder, e EchoOrGroup, postResource PostResource, postsCollectionResource PostsCollectionResource, starsResource StarsResource) {
	ctrlAdder.AddPaths([]string{"/stream/0/posts/:post_id"}, e, NewPostResourceController(postResource))
	ctrlAdder.AddPaths([]string{"/stream/0/posts"}, e, NewPostsCollectionResourceController(postsCollectionResource))
	ctrlAdder.AddPaths([]string{"/stream/0/posts/:post_id/star"}, e, NewStarsResourceController(starsResource))
}
