/*
 * Copyright © 2018-2020 Musing Studio LLC.
 *
 * This file is part of WriteFreely.
 *
 * WriteFreely is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License, included
 * in the LICENSE file in this source code package.
 */

// Package parse assists in the parsing of plain text posts
package parse

import (
	"github.com/writeas/web-core/stringmanip"
	"regexp"
	"strings"
)

var (
	titleElementReg = regexp.MustCompile("</?p>")
	urlReg          = regexp.MustCompile("https?://")
	imgReg          = regexp.MustCompile(`!\[([^]]+)\]\([^)]+\)`)
)

// PostLede attempts to extract the first thought of the given post, generally
// contained within the first line or sentence of text.
func PostLede(t string, includePunc bool) string {
	// Adjust where we truncate if we want to include punctuation
	iAdj := 0
	if includePunc {
		iAdj = 1
	}

	// Find lede within first line of text
	nl := strings.IndexRune(t, '\n')
	if nl > -1 {
		t = t[:nl]
	}

	// Strip certain HTML tags
	t = titleElementReg.ReplaceAllString(t, "")

	// Strip URL protocols
	t = urlReg.ReplaceAllString(t, "")

	// Strip image URL, leaving only alt text
	t = imgReg.ReplaceAllString(t, " $1 ")

	// Find lede within first sentence
	punc := strings.Index(t, ". ")
	if punc > -1 {
		t = t[:punc+iAdj]
	}
	punc = stringmanip.IndexRune(t, '。')
	if punc > -1 {
		c := []rune(t)
		t = string(c[:punc+iAdj])
	}
	punc = stringmanip.IndexRune(t, '?')
	if punc > -1 {
		c := []rune(t)
		t = string(c[:punc+iAdj])
	}

	return t
}

// TruncToWord truncates the given text to the provided limit.
func TruncToWord(s string, l int) (string, bool) {
	truncated := false
	c := []rune(s)
	if len(c) > l {
		truncated = true
		s = string(c[:l])
		spaceIdx := strings.LastIndexByte(s, ' ')
		if spaceIdx > -1 {
			s = s[:spaceIdx]
		}
	}
	return s, truncated
}

// Truncate truncates the given text to the provided limit, returning the original string if it's shorter than the limit.
func Truncate(s string, l int) string {
	c := []rune(s)
	if len(c) > l {
		s = string(c[:l])
	}
	return s
}
