package main

import (
	"encoding/json"
	"fmt"
	"html/template"
	"net/http"
	"strings"

	"github.com/golang/glog"

	"code.hackerspace.pl/hscloud/hswaw/site/calendar"
	"code.hackerspace.pl/hscloud/hswaw/site/templates"
)

// parseTemplates parses a set of templates from
// //hswaw/site/templates/$name.html into a Go HTML template. Typical Go text
// templating ordering behaviour applies (this basically replicates
// template.ParseFiles, but for statically embedded files instead).
func parseTemplates(names ...string) (*template.Template, error) {
	if len(names) == 0 {
		return nil, fmt.Errorf("at least one template must be given")
	}

	var t *template.Template
	for _, n := range names {
		path := fmt.Sprintf("hswaw/site/templates/%s.html", n)
		data, ok := templates.Data[path]
		if !ok {
			return nil, fmt.Errorf("template %q (%s) not found", n, path)
		}
		s := string(data)

		if t == nil {
			t = template.New(n)
		}
		_, err := t.Parse(s)
		if err != nil {
			return nil, fmt.Errorf("template %q could not be parsed: %w", n, err)
		}
	}
	return t, nil
}

var (
	tmplIndex = template.Must(parseTemplates("index"))
)

// render attempts to render a given Go template with data into the HTTP
// response writer, and logs a warning if anything goes wrong.
func render(w http.ResponseWriter, t *template.Template, data interface{}) {
	if err := t.Execute(w, data); err != nil {
		glog.Warningf("Rendering %v failed: %v", t, err)
	}
}

// handleIndex handles rendering the main page at /.
func (s *service) handleIndex(w http.ResponseWriter, r *http.Request) {
	// Necessary as "/" is a catch-all in net/http.
	if r.URL.Path != "/" {
		http.NotFound(w, r)
		return
	}

	ctx := r.Context()

	atStatus, atError := getAt(ctx)

	render(w, tmplIndex, map[string]interface{}{
		"Entries":  s.getFeeds(),
		"Events":   s.getEvents(),
		"AtStatus": atStatus,
		"AtError":  atError,
	})
}

func (s *service) handleRobotsTxt(w http.ResponseWriter, r *http.Request) {
	// Allow everyone everywhere. We don't really host much on hackerspace.pl anyway.
	fmt.Fprintf(w, "User-agent: *\n")
	fmt.Fprintf(w, "Allow: /\n")
}

func (s *service) handleJSONEvents(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(s.getEvents())
}

// handleEvent is a fallback HTML-only event render view.
// TODO(q3k): make this pretty by either making a template or redirecting to a
// pretty viewer.
func (s *service) handleEvent(w http.ResponseWriter, r *http.Request) {
	parts := strings.Split(r.URL.Path, "/")
	uid := parts[len(parts)-1]

	events := s.getEvents()
	var event *calendar.UpcomingEvent
	for _, ev := range events {
		if ev.UID == uid {
			event = ev
			break
		}
	}
	if event == nil {
		http.NotFound(w, r)
		return
	}

	render(w, template.Must(template.New("event").Parse(`<!DOCTYPE html>
	<meta charset="utf-8">
	<title>Event details: {{ .Summary }}</title>
	<body>
	<i>this interface intentionally left ugly...</i><br/>
	<b>summary:</b> {{ .Summary }}<br />
	<b>date:</b> {{ .WarsawDate }}<br />
	<pre>{{ .Description }}</pre>`)), event)
}

func (s *service) handleSpaceAPI(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(generateSpaceAPIResponse(ctx))
}
