package main

import (
	"strings"

	"github.com/yuin/goldmark"
	"github.com/yuin/goldmark/ast"
	"github.com/yuin/goldmark/parser"
	"github.com/yuin/goldmark/text"
	"github.com/yuin/goldmark/util"
)

type extLinksTransformer struct{}

func (extLinksTransformer) Transform(doc *ast.Document, reader text.Reader, pc parser.Context) {
	ast.Walk(doc, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
		if !entering {
			return ast.WalkContinue, nil
		}
		link, ok := n.(*ast.Link)
		if !ok {
			return ast.WalkContinue, nil
		}
		if isExternalURL(string(link.Destination)) {
			link.SetAttribute([]byte("target"), []byte("_blank"))
			link.SetAttribute([]byte("rel"), []byte("noopener noreferrer"))
		}
		return ast.WalkContinue, nil
	})
}

func isExternalURL(dest string) bool {
	if strings.HasPrefix(dest, "//") {
		return true
	}
	i := strings.Index(dest, ":")
	if i <= 0 {
		return false
	}
	for _, c := range dest[:i] {
		if !(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z') &&
			!(c >= '0' && c <= '9') && c != '+' && c != '-' && c != '.' {
			return false
		}
	}
	return true
}

type extLinksExt struct{}

func newExtLinksExt() goldmark.Extender { return &extLinksExt{} }

func (e *extLinksExt) Extend(m goldmark.Markdown) {
	m.Parser().AddOptions(parser.WithASTTransformers(
		util.Prioritized(extLinksTransformer{}, 999),
	))
}
