// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package comment

import (
	
	
	
)

// An htmlPrinter holds the state needed for printing a [Doc] as HTML.
type htmlPrinter struct {
	*Printer
	tight bool
}

// HTML returns an HTML formatting of the [Doc].
// See the [Printer] documentation for ways to customize the HTML output.
func ( *Printer) ( *Doc) []byte {
	 := &htmlPrinter{Printer: }
	var  bytes.Buffer
	for ,  := range .Content {
		.block(&, )
	}
	return .Bytes()
}

// block prints the block x to out.
func ( *htmlPrinter) ( *bytes.Buffer,  Block) {
	switch x := .(type) {
	default:
		fmt.Fprintf(, "?%T", )

	case *Paragraph:
		if !.tight {
			.WriteString("<p>")
		}
		.text(, .Text)
		.WriteString("\n")

	case *Heading:
		.WriteString("<h")
		 := strconv.Itoa(.headingLevel())
		.WriteString()
		if  := .headingID();  != "" {
			.WriteString(` id="`)
			.escape(, )
			.WriteString(`"`)
		}
		.WriteString(">")
		.text(, .Text)
		.WriteString("</h")
		.WriteString()
		.WriteString(">\n")

	case *Code:
		.WriteString("<pre>")
		.escape(, .Text)
		.WriteString("</pre>\n")

	case *List:
		 := "ol>\n"
		if .Items[0].Number == "" {
			 = "ul>\n"
		}
		.WriteString("<")
		.WriteString()
		 := "1"
		for ,  := range .Items {
			.WriteString("<li")
			if  := .Number;  != "" {
				if  !=  {
					.WriteString(` value="`)
					.WriteString()
					.WriteString(`"`)
					 = 
				}
				 = inc()
			}
			.WriteString(">")
			.tight = !.BlankBetween()
			for ,  := range .Content {
				.(, )
			}
			.tight = false
		}
		.WriteString("</")
		.WriteString()
	}
}

// inc increments the decimal string s.
// For example, inc("1199") == "1200".
func inc( string) string {
	 := []byte()
	for  := len() - 1;  >= 0; -- {
		if [] < '9' {
			[]++
			return string()
		}
		[] = '0'
	}
	return "1" + string()
}

// text prints the text sequence x to out.
func ( *htmlPrinter) ( *bytes.Buffer,  []Text) {
	for ,  := range  {
		switch t := .(type) {
		case Plain:
			.escape(, string())
		case Italic:
			.WriteString("<i>")
			.escape(, string())
			.WriteString("</i>")
		case *Link:
			.WriteString(`<a href="`)
			.escape(, .URL)
			.WriteString(`">`)
			.(, .Text)
			.WriteString("</a>")
		case *DocLink:
			 := .docLinkURL()
			if  != "" {
				.WriteString(`<a href="`)
				.escape(, )
				.WriteString(`">`)
			}
			.(, .Text)
			if  != "" {
				.WriteString("</a>")
			}
		}
	}
}

// escape prints s to out as plain text,
// escaping < & " ' and > to avoid being misinterpreted
// in larger HTML constructs.
func ( *htmlPrinter) ( *bytes.Buffer,  string) {
	 := 0
	for  := 0;  < len(); ++ {
		switch [] {
		case '<':
			.WriteString([:])
			.WriteString("&lt;")
			 =  + 1
		case '&':
			.WriteString([:])
			.WriteString("&amp;")
			 =  + 1
		case '"':
			.WriteString([:])
			.WriteString("&quot;")
			 =  + 1
		case '\'':
			.WriteString([:])
			.WriteString("&apos;")
			 =  + 1
		case '>':
			.WriteString([:])
			.WriteString("&gt;")
			 =  + 1
		}
	}
	.WriteString([:])
}