package blog

import (
	"encoding/xml"
	"fmt"
	"strings"
	"time"
)

const baseURL = "https://chaosmith.systems"

func generateRSS(s *Store) string {
	var b strings.Builder
	b.WriteString(`<?xml version="1.0" encoding="UTF-8"?>` + "\n")
	b.WriteString(`<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">` + "\n")
	b.WriteString("  <channel>\n")
	b.WriteString("    <title>Chaosmith Systems — Field Notes</title>\n")
	b.WriteString("    <link>" + baseURL + "/blog/</link>\n")
	b.WriteString("    <description>Engineering, music, and experiments from controlled chaos.</description>\n")
	b.WriteString("    <language>en</language>\n")
	b.WriteString(`    <atom:link href="` + baseURL + `/blog/feed.xml" rel="self" type="application/rss+xml"/>` + "\n")

	for _, p := range s.All() {
		b.WriteString("    <item>\n")
		b.WriteString("      <title>" + xmlEscape(p.Title) + "</title>\n")
		b.WriteString("      <link>" + baseURL + "/blog/posts/" + p.Slug + "</link>\n")
		b.WriteString("      <guid>" + baseURL + "/blog/posts/" + p.Slug + "</guid>\n")
		b.WriteString("      <description>" + xmlEscape(p.Description) + "</description>\n")
		b.WriteString("      <pubDate>" + p.Date.Format(time.RFC1123Z) + "</pubDate>\n")
		b.WriteString("    </item>\n")
	}

	b.WriteString("  </channel>\n</rss>\n")
	return b.String()
}

func generateJSONFeed(s *Store) string {
	var b strings.Builder
	b.WriteString(`{"version":"https://jsonfeed.org/version/1.1","title":"Chaosmith Systems — Field Notes","home_page_url":"` + baseURL + `/blog/","feed_url":"` + baseURL + `/blog/feed.json","items":[`)

	first := true
	for _, p := range s.All() {
		if !first {
			b.WriteString(",")
		}
		first = false
		b.WriteString(`{`)
		b.WriteString(`"id":"` + baseURL + "/blog/posts/" + p.Slug + `",`)
		b.WriteString(`"url":"` + baseURL + "/blog/posts/" + p.Slug + `",`)
		b.WriteString(`"title":"` + jsonEscape(p.Title) + `",`)
		b.WriteString(`"summary":"` + jsonEscape(p.Description) + `",`)
		b.WriteString(`"date_published":"` + p.Date.Format(time.RFC3339) + `"`)
		b.WriteString(`}`)
	}

	b.WriteString("]}")
	return b.String()
}

func generateSitemap(s *Store) string {
	var b strings.Builder
	b.WriteString(`<?xml version="1.0" encoding="UTF-8"?>` + "\n")
	b.WriteString(`<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">` + "\n")

	// Static pages
	b.WriteString("  <url>\n")
	b.WriteString("    <loc>" + baseURL + "/</loc>\n")
	b.WriteString("    <changefreq>monthly</changefreq>\n")
	b.WriteString("  </url>\n")
	b.WriteString("  <url>\n")
	b.WriteString("    <loc>" + baseURL + "/blog/</loc>\n")
	b.WriteString("    <changefreq>weekly</changefreq>\n")
	b.WriteString("  </url>\n")

	for _, p := range s.All() {
		b.WriteString("  <url>\n")
		b.WriteString("    <loc>" + baseURL + "/blog/posts/" + p.Slug + "</loc>\n")
		b.WriteString("    <lastmod>" + p.Date.Format("2006-01-02") + "</lastmod>\n")
		b.WriteString("  </url>\n")
	}

	b.WriteString("</urlset>\n")
	return b.String()
}

func xmlEscape(s string) string {
	var b strings.Builder
	xml.EscapeText(&b, []byte(s))
	return b.String()
}

func jsonEscape(s string) string {
	var b strings.Builder
	for _, r := range s {
		switch r {
		case '"':
			b.WriteString(`\"`)
		case '\\':
			b.WriteString(`\\`)
		case '\n':
			b.WriteString(`\n`)
		case '\r':
			b.WriteString(`\r`)
		case '\t':
			b.WriteString(`\t`)
		default:
			if r < 0x20 {
				b.WriteString(fmt.Sprintf(`\u%04x`, r))
			} else {
				b.WriteRune(r)
			}
		}
	}
	return b.String()
}
