// FilterParam adds the middleware filter iff the URL parameter exists.
func (r *Router) FilterParam(param string, filter http.HandlerFunc) {
	r.Filter(func(w http.ResponseWriter, req *http.Request) {
		c := context.Get(req)
		if len(c.Params.Get(param)) > 0 {
			filter(w, req)
		}
	})
}
// Required by http.Handler interface. This method is invoked by the
// http server and will handle all page routing
func (r *Router) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	r.RLock()
	defer r.RUnlock()

	//wrap the response writer in our custom interface
	w := &responseWriter{writer: rw, Router: r}

	//find a matching Route
	for _, route := range r.routes {

		//if the methods don't match, skip this handler
		//i.e if request.Method is 'PUT' Route.Method must be 'PUT'
		if req.Method != route.method {
			continue
		}

		//check if Route pattern matches url
		if !route.regex.MatchString(req.URL.Path) {
			continue
		}

		//get submatches (params)
		matches := route.regex.FindStringSubmatch(req.URL.Path)

		//double check that the Route matches the URL pattern.
		if len(matches[0]) != len(req.URL.Path) {
			continue
		}

		//create the http.Requests context
		c := context.Get(req)

		//add url parameters to the context
		for i, match := range matches[1:] {
			c.Params.Set(route.params[i], match)
		}

		//execute middleware filters
		for _, filter := range r.filters {
			filter(w, req)
			if w.started {
				return
			}
		}

		//invoke the request handler
		route.handler(w, req)
		return
	}

	//if no matches to url, throw a not found exception
	if w.started == false {
		http.NotFound(w, req)
	}
}
// TestFilter tests that a route is filtered prior to handling
func TestRouteFilter(t *testing.T) {

	r, _ := http.NewRequest("GET", "/person/anderson/thomas?learn=kungfu", nil)
	w := httptest.NewRecorder()

	mux := New()
	mux.Filter(HandlerSetVar)
	mux.Get("/person/:last/:first", HandlerOk)
	mux.ServeHTTP(w, r)

	c := context.Get(r)
	password := c.Values.Get("password")

	if password != "z1on" {
		t.Errorf("session variable set to [%s]; want [%s]", password, "z1on")
	}
	if w.Body.String() != "hello world" {
		t.Errorf("Body set to [%s]; want [%s]", w.Body.String(), "hello world")
	}
}
// TestRouteOk tests that the route is correctly handled, and the URL parameters
// are added to the Context.
func TestRouteOk(t *testing.T) {

	r, _ := http.NewRequest("GET", "/person/anderson/thomas?learn=kungfu", nil)
	w := httptest.NewRecorder()

	mux := New()
	mux.Get("/person/:last/:first", HandlerOk)
	mux.ServeHTTP(w, r)

	c := context.Get(r)
	lastNameParam := c.Params.Get("last")
	firstNameParam := c.Params.Get("first")

	if lastNameParam != "anderson" {
		t.Errorf("url param set to [%s]; want [%s]", lastNameParam, "anderson")
	}
	if firstNameParam != "thomas" {
		t.Errorf("url param set to [%s]; want [%s]", firstNameParam, "thomas")
	}
	if w.Body.String() != "hello world" {
		t.Errorf("Body set to [%s]; want [%s]", w.Body.String(), "hello world")
	}
}
func HandlerSetVar(w http.ResponseWriter, r *http.Request) {
	c := context.Get(r)
	c.Values.Set("password", "z1on")
}