package main

import "strconv"

// TOCItem is one entry in the Inhaltsverzeichnis.
type TOCItem struct {
	Level   int
	Title   string
	PageStr string // formatted page number (Roman or Arabic)
}

// TableItem is one entry in the Tabellenverzeichnis.
type TableItem struct {
	Title   string
	PageStr string
}

// FigureItem is one entry in the Abbildungsverzeichnis.
type FigureItem struct {
	Title   string
	PageStr string
}

// dirEntry is the internal representation used by renderDirEntries.
type dirEntry struct {
	indent  int    // indentation level (0 = none)
	title   string // translated title text
	pageStr string // page number string
}

// RecordHeader adds a heading to the TOC with the appropriate page number.
// Front-matter headings use Roman numerals; main-body headings use Arabic.
// Headings on the title page (NumNone) are not recorded.
func (r *IHKRenderer) RecordHeader(level int, title string) {
	var pageStr string
	switch r.numType {
	case NumRoman:
		pageStr = toRoman(r.pdf.PageNo())
	case NumArabic:
		dp := r.pdf.PageNo() - r.pageOffset
		if dp <= 0 {
			dp = 1
		}
		pageStr = strconv.Itoa(dp)
	default:
		return
	}
	r.tocItems = append(r.tocItems, TOCItem{Level: level, Title: title, PageStr: pageStr})
}

// RecordTable adds an entry to the Tabellenverzeichnis.
func (r *IHKRenderer) RecordTable(title string) {
	dp := r.pdf.PageNo() - r.pageOffset
	if dp <= 0 {
		dp = 1
	}
	r.tableItems = append(r.tableItems, TableItem{Title: title, PageStr: strconv.Itoa(dp)})
}

// RecordFigure adds an entry to the Abbildungsverzeichnis.
func (r *IHKRenderer) RecordFigure(title string) {
	dp := r.pdf.PageNo() - r.pageOffset
	if dp <= 0 {
		dp = 1
	}
	r.figureItems = append(r.figureItems, FigureItem{Title: title, PageStr: strconv.Itoa(dp)})
}

// RenderTOC renders the Inhaltsverzeichnis on a new Roman-numbered page.
// In pass 1 the list is empty (no tocItems yet); pass 2 fills it in.
// Note: if the TOC spans more pages than in pass 1, subsequent page numbers
// will be off by the difference — an inherent two-pass limitation.
func (r *IHKRenderer) RenderTOC() {
	r.numType = NumRoman
	r.pdf.AddPage()

	r.pdf.SetFont("Helvetica", "B", dinFontHeading)
	r.pdf.CellFormat(0, dinLineHtHeading+4, r.tr("Inhaltsverzeichnis"), "", 1, "L", false, 0, "")
	r.pdf.Ln(dinSpaceAfterHeading)

	if len(r.tocItems) == 0 {
		return
	}

	// Column header row
	uw := r.usableWidth()
	r.pdf.SetFont("Helvetica", "B", dinFontBody)
	r.pdf.CellFormat(uw-20, dinLineHtBody, r.tr("Inhalt"), "", 0, "L", false, 0, "")
	r.pdf.CellFormat(20, dinLineHtBody, r.tr("Seite"), "", 1, "R", false, 0, "")
	r.pdf.Ln(2)

	entries := make([]dirEntry, len(r.tocItems))
	for i, item := range r.tocItems {
		entries[i] = dirEntry{
			indent:  item.Level - 1,
			title:   item.Title,
			pageStr: item.PageStr,
		}
	}
	r.renderDirEntries(entries)
}

// RenderListOfTables renders the Tabellenverzeichnis if any tables were recorded.
func (r *IHKRenderer) RenderListOfTables() {
	if len(r.tableItems) == 0 {
		return
	}
	r.pdf.AddPage()
	r.pdf.SetFont("Helvetica", "B", dinFontHeading)
	r.pdf.CellFormat(0, dinLineHtHeading+4, r.tr("Tabellenverzeichnis"), "", 1, "L", false, 0, "")
	r.pdf.Ln(dinSpaceAfterHeading)

	entries := make([]dirEntry, len(r.tableItems))
	for i, item := range r.tableItems {
		entries[i] = dirEntry{indent: 0, title: item.Title, pageStr: item.PageStr}
	}
	r.renderDirEntries(entries)
}

// RenderListOfFigures renders the Abbildungsverzeichnis if any figures were recorded.
func (r *IHKRenderer) RenderListOfFigures() {
	if len(r.figureItems) == 0 {
		return
	}
	r.pdf.AddPage()
	r.pdf.SetFont("Helvetica", "B", dinFontHeading)
	r.pdf.CellFormat(0, dinLineHtHeading+4, r.tr("Abbildungsverzeichnis"), "", 1, "L", false, 0, "")
	r.pdf.Ln(dinSpaceAfterHeading)

	entries := make([]dirEntry, len(r.figureItems))
	for i, item := range r.figureItems {
		entries[i] = dirEntry{indent: 0, title: item.Title, pageStr: item.PageStr}
	}
	r.renderDirEntries(entries)
}

// renderDirEntries renders a list of title/page entries with dot leaders,
// per DIN 5008 Inhaltsverzeichnis layout.
func (r *IHKRenderer) renderDirEntries(entries []dirEntry) {
	uw := r.usableWidth()
	lm, _, _, _ := r.pdf.GetMargins()
	r.pdf.SetFont("Helvetica", "", dinFontBody)

	for _, e := range entries {
		indent := float64(e.indent * 8)
		r.pdf.SetX(lm + indent)

		title := r.tr(e.title)
		pageStr := e.pageStr
		tw := r.pdf.GetStringWidth(title)
		pw := r.pdf.GetStringWidth(pageStr)
		avail := uw - indent - tw - pw - 6

		r.pdf.CellFormat(tw+2, dinLineHtBody, title, "", 0, "L", false, 0, "")
		if avail > 0 {
			dots := ""
			dw := r.pdf.GetStringWidth(".")
			if dw > 0 {
				for float64(len([]rune(dots)))*dw < avail {
					dots += "."
				}
			}
			r.pdf.CellFormat(avail, dinLineHtBody, dots, "", 0, "L", false, 0, "")
		}
		r.pdf.CellFormat(pw+4, dinLineHtBody, pageStr, "", 1, "R", false, 0, "")
	}
}
