package router

import (
	"net/http"
	"regexp"
	"strings"
)

type Handler func(*Context)

type Router struct {
	middle []Handler
	routes []Route
	base   string
}

type Route struct {
	regex *regexp.Regexp
	chain []Handler
}

func NewRouter(base string) *Router {
	router := &Router{}
	router.middle = make([]Handler, 0)
	router.routes = make([]Route, 0)
	router.base = base
	return router
}

func (r *Router) Use(h Handler) {
	r.middle = append(r.middle, h)
}

func (r *Router) For(path string, handler Handler) {
	chain := make([]Handler, 0)
	chain = append(chain, r.middle...)
	chain = append(chain, handler)

	x := Route{}
	x.regex = routeRegexp(path)
	x.chain = chain
	r.routes = append(r.routes, x)
}

func (r *Router) resolve(path string) *Route {
	for _, route := range r.routes {
		if route.regex.MatchString(path) {
			return &route
		}
	}
	return nil
}

func (r *Router) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	// autoclose open base url
	if r.base != "" {
		if r.base == req.URL.Path {
			http.Redirect(rw, req, r.base+"/", http.StatusFound)
			return
		}
		if !strings.HasPrefix(req.URL.Path, r.base) {
			rw.WriteHeader(http.StatusNotFound)
			return
		}
	}

	path := strings.TrimPrefix(req.URL.Path, r.base)

	route := r.resolve(path)
	if route == nil {
		rw.WriteHeader(http.StatusNotFound)
		return
	}

	context := &Context{}
	context.Req = req
	context.Out = rw
	context.Vars = regexGroups(path, route.regex)
	context.index = -1
	context.chain = route.chain
	context.Next()
}
