func ImageListHandler(writer http.ResponseWriter, req *http.Request) {
	TAG := "panopticon.ImageListHandler"
	notFound := httputil.NewJSONAssertable(writer, TAG, http.StatusNotFound, missingImage)
	badReq := httputil.NewJSONAssertable(writer, TAG, http.StatusBadRequest, clientError)
	ise := httputil.NewJSONAssertable(writer, TAG, http.StatusInternalServerError, internalError)

	camera := httputil.ExtractSegment(req.URL.Path, 3)
	kindstr := httputil.ExtractSegment(req.URL.Path, 4)
	badReq.Assert(camera != "" && kindstr != "", "missing camera (%s) or kind (%s)", camera, kindstr)

	kind := Repository.segmentToMediaKind(kindstr)
	badReq.Assert(kind != MediaUnknown, "request for invalid kind '%s'", kindstr)

	u := userFor(req)
	cam := System.GetCamera(camera)
	notFound.Assert(cam != nil, "request for unknown camera '%s'", camera)
	notFound.Assert(!cam.Private || u.Privileged, "attempt by '%s' to access private '%s'", u.Email, cam.ID)

	imgs := Repository.ListKind(camera, kind)

	// reverse sort by timestamp
	sort.Slice(imgs, func(i, j int) bool { return imgs[i].Timestamp.After(imgs[j].Timestamp) })

	skip := 0
	per := 0

	err := req.ParseForm()
	ise.Assert(err == nil, "error parsing request form (%s)", err)

	raw := req.Form.Get("skip")
	if raw != "" {
		skip, err = strconv.Atoi(raw)
		badReq.Assert(err == nil, "unparseable skip value '%s' (%s)", raw, err)
	}
	raw = req.Form.Get("per")
	if raw != "" {
		per, err = strconv.Atoi(raw)
		badReq.Assert(err == nil, "unparseable per value '%s' (%s)", raw, err)
	}

	res := []*messages.ImageMeta{}

	if skip < len(imgs) {
		end := len(imgs)
		if skip+per < end {
			end = skip + per
		}
		loc := cam.Location()
		if loc == nil {
			loc = time.UTC
		}
		for _, img := range imgs[skip:end] {
			ts := img.Timestamp.In(loc)
			meta := &messages.ImageMeta{
				Camera:   cam.Name,
				Handle:   img.Handle,
				Time:     ts.Format("3:04pm"),
				Date:     ts.Format("Monday, 2 January, 2006"),
				HasVideo: img.HasVideo,
			}
			res = append(res, meta)
		}
	} // else we're past the end, so return no results

	httputil.SendJSON(writer, http.StatusOK, &APIResponse{Artifact: &messages.ImageList{Camera: cam.Name, Total: len(imgs), Images: res}})
}
// ImageListHandler handles /client/images
ImageListHandler handles /client/images
// ImageListHandler handles / client / images
func ImageListHandler(writer http.ResponseWriter, req *http.Request) {
	TAG := "panopticon.ImageListHandler"
	notFound := httputil.NewJSONAssertable(writer, TAG, http.StatusNotFound, missingImage)
	badReq := httputil.NewJSONAssertable(writer, TAG, http.StatusBadRequest, clientError)
	ise := httputil.NewJSONAssertable(writer, TAG, http.StatusInternalServerError, internalError)
	camera := httputil.ExtractSegment(req.URL.Path, 3)
	kindstr := httputil.ExtractSegment(req.URL.Path, 4)
	badReq.Assert(camera != "" && kindstr != "", "missing camera (%s) or kind (%s)", camera, kindstr)
	kind := Repository.segmentToMediaKind(kindstr)
	badReq.Assert(kind != MediaUnknown, "request for invalid kind '%s'", kindstr)
	u := userFor(req)
	cam := System.GetCamera(camera)
	notFound.Assert(cam != nil, "request for unknown camera '%s'", camera)
	notFound.Assert(!cam.Private || u.Privileged, "attempt by '%s' to access private '%s'", u.Email, cam.ID)
	imgs := Repository.ListKind(camera, kind)
	sort.Slice(imgs, func(i, j int) bool { return imgs[i].Timestamp.After(imgs[j].Timestamp) })
	skip := 0
	per := 0
	err := req.ParseForm()
	ise.Assert(err == nil, "error parsing request form (%s)", err)
	raw := req.Form.Get("skip")
	if raw != "" {
		skip, err = strconv.Atoi(raw)
		badReq.Assert(err == nil, "unparseable skip value '%s' (%s)", raw, err)
	}
	raw = req.Form.Get("per")
	if raw != "" {
		per, err = strconv.Atoi(raw)
		badReq.Assert(err == nil, "unparseable per value '%s' (%s)", raw, err)
	}
	res := []*messages.ImageMeta{}
	if skip < len(imgs) {
		end := len(imgs)
		if skip+per < end {
			end = skip + per
		}
		loc := cam.Location()
		if loc == nil {
			loc = time.UTC
		}
		for _, img := range imgs[skip:end] {
			ts := img.Timestamp.In(loc)
			meta := &messages.ImageMeta{
				Camera:   cam.Name,
				Handle:   img.Handle,
				Time:     ts.Format("3:04pm"),
				Date:     ts.Format("Monday, 2 January, 2006"),
				HasVideo: img.HasVideo,
			}
			res = append(res, meta)
		}
	} 
	httputil.SendJSON(writer, http.StatusOK, &APIResponse{Artifact: &messages.ImageList{Camera: cam.Name, Total: len(imgs), Images: res}})
}
func ImageListHandler ( writer http . ResponseWriter , req * http . Request ) { TAG := " " notFound := httputil . NewJSONAssertable ( writer , TAG , http . StatusNotFound , missingImage ) badReq := httputil . NewJSONAssertable ( writer , TAG , http . StatusBadRequest , clientError ) ise := httputil . NewJSONAssertable ( writer , TAG , http . StatusInternalServerError , internalError ) camera := httputil . ExtractSegment ( req . URL . Path , 3 ) kindstr := httputil . ExtractSegment ( req . URL . Path , 4 ) badReq . Assert ( camera != " " && kindstr != " " , " " , camera , kindstr ) kind := Repository . segmentToMediaKind ( kindstr ) badReq . Assert ( kind != MediaUnknown , " " , kindstr ) u := userFor ( req ) cam := System . GetCamera ( camera ) notFound . Assert ( cam != nil , " " , camera ) notFound . Assert ( ! cam . Private || u . Privileged , " " , u . Email , cam . ID ) imgs := Repository . ListKind ( camera , kind ) sort . Slice ( imgs , func ( i , j int ) bool { return imgs [ i ] . Timestamp . After ( imgs [ j ] . Timestamp ) } ) skip := 0 per := 0 err := req . ParseForm ( ) ise . Assert ( err == nil , " " , err ) raw := req . Form . Get ( " " ) if raw != " " { skip , err = strconv . Atoi ( raw ) badReq . Assert ( err == nil , " " , raw , err ) } raw = req . Form . Get ( " " ) if raw != " " { per , err = strconv . Atoi ( raw ) badReq . Assert ( err == nil , " " , raw , err ) } res := [ ] * messages . ImageMeta { } if skip < len ( imgs ) { end := len ( imgs ) if skip + per < end { end = skip + per } loc := cam . Location ( ) if loc == nil { loc = time . UTC } for _ , img := range imgs [ skip : end ] { ts := img . Timestamp . In ( loc ) meta := & messages . ImageMeta { Camera : cam . Name , Handle : img . Handle , Time : ts . Format ( " " ) , Date : ts . Format ( " " ) , HasVideo : img . HasVideo , } res = append ( res , meta ) } } httputil . SendJSON ( writer , http . StatusOK , & APIResponse { Artifact : & messages . ImageList { Camera : cam . Name , Total : len ( imgs ) , Images : res } } ) }
ImageListHandler handles /client/images
ImageListHandler handles / client / images
// reverse sort by timestamp // else we're past the end, so return no results