package blog

import (
	"html/template"
	"io/ioutil"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"time"

	"christine.website/internal/front"
	"github.com/russross/blackfriday"
)

// Post is a single blogpost.
type Post struct {
	Title      string        `json:"title"`
	Link       string        `json:"link"`
	Summary    string        `json:"summary,omitifempty"`
	Body       string        `json:"-"`
	BodyHTML   template.HTML `json:"body"`
	Date       time.Time
	DateString string `json:"date"`
}

// Posts implements sort.Interface for a slice of Post objects.
type Posts []Post

func (p Posts) Len() int { return len(p) }
func (p Posts) Less(i, j int) bool {
	iDate := p[i].Date
	jDate := p[j].Date

	return iDate.Unix() < jDate.Unix()
}
func (p Posts) Swap(i, j int) { p[i], p[j] = p[j], p[i] }

// LoadPosts loads posts for a given directory.
func LoadPosts(path string) (Posts, error) {
	type postFM struct {
		Title string
		Date  string
	}
	var result Posts

	err := filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if info.IsDir() {
			return nil
		}

		fin, err := os.Open(path)
		if err != nil {
			return err
		}
		defer fin.Close()

		content, err := ioutil.ReadAll(fin)
		if err != nil {
			return err
		}

		var fm postFM
		remaining, err := front.Unmarshal(content, &fm)
		if err != nil {
			return err
		}

		output := blackfriday.Run(remaining)

		const timeFormat = `2006-01-02`
		date, err := time.Parse(timeFormat, fm.Date)
		if err != nil {
			return err
		}

		p := Post{
			Title:      fm.Title,
			Date:       date,
			DateString: fm.Date,
			Link:       strings.Split(path, ".")[0],
			Body:       string(remaining),
			BodyHTML:   template.HTML(output),
		}
		result = append(result, p)

		return nil
	})
	if err != nil {
		return nil, err
	}

	sort.Sort(sort.Reverse(result))

	return result, nil
}
