package main

import (
	"encoding/json"
	"github.com/gorilla/mux"
	"log"
	"net/http"
)

//------ Backend mocking

type Item struct {
	Name string
}

type Backend struct {
}

func (b *Backend) GetItems() []Item {
	return []Item{
		{Name: "hello"},
		{Name: "world"},
	}
}

//------ Backend mocking

type Route struct {
	Pattern string
	Method  string
	handler http.HandlerFunc
}

type Routes []Route

var routes = Routes{
	Route{
		Pattern: "list",
		Method:  http.MethodGet,
		handler: (*Api).ListHandler, // <- Problem here
	},
}

type Api struct {
	Router  *mux.Router
	Backend Backend
	Routes  []Route
}

// Return a new instance of the API
func NewApi(backend Backend) *Api {

	return &Api{
		Router:  mux.NewRouter(),
		Backend: backend,
		Routes:  routes,
	}
}

// ListHandler - Start the API
func (api *Api) Start() {

	// Register all routes
	for _, r := range api.Routes {
		api.registerRoute(r)
	}

	// Start the API listener
	log.Fatal(http.ListenAndServe(":7070", api.Router))
}

// registerRoute - Register a rout with the
func (api *Api) registerRoute(route Route) bool {

	api.Router.HandleFunc(route.Pattern, route.handler).Methods(route.Method)

	return true
}

// ListHandler - Handlers requests for item listing
func (api *Api) ListHandler(w http.ResponseWriter, r *http.Request) {
	items := api.Backend.GetItems()

	err := json.NewEncoder(w).Encode(items)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
}

//------ This would be in a different package
func main() {
	api := NewApi(Backend{})
	api.Start()
}
