package ast

import (
	
	
	
	
	
)

// Print is for debugging. It prints a string representation of parsed
// markdown doc (result of parser.Parse()) to dst.
//
// To make output readable, it shortens text output.
func ( io.Writer,  Node) {
	PrintWithPrefix(, , "  ")
}

// PrintWithPrefix is like Print but allows customizing prefix used for
// indentation. By default it's 2 spaces. You can change it to e.g. tab
// by passing "\t"
func ( io.Writer,  Node,  string) {
	// for more compact output, don't print outer Document
	if ,  := .(*Document);  {
		for ,  := range .GetChildren() {
			printRecur(, , , 0)
		}
	} else {
		printRecur(, , , 0)
	}
}

// ToString is like Dump but returns result as a string
func ( Node) string {
	var  bytes.Buffer
	Print(&, )
	return .String()
}

func contentToString( []byte,  []byte) string {
	if  != nil {
		return string()
	}
	if  != nil {
		return string()
	}
	return ""
}

func getContent( Node) string {
	if  := .AsContainer();  != nil {
		return contentToString(.Literal, .Content)
	}
	 := .AsLeaf()
	return contentToString(.Literal, .Content)
}

func shortenString( string,  int) string {
	// for cleaner, one-line ouput, replace some white-space chars
	// with their escaped version
	 = strings.Replace(, "\n", `\n`, -1)
	 = strings.Replace(, "\r", `\r`, -1)
	 = strings.Replace(, "\t", `\t`, -1)
	if  < 0 {
		return 
	}
	if utf8.RuneCountInString() <  {
		return 
	}
	// add "…" to indicate truncation
	return string(append([]rune()[:-3], '…'))
}

// get a short name of the type of v which excludes package name
// and strips "()" from the end
func getNodeType( Node) string {
	 := fmt.Sprintf("%T", )
	 = strings.TrimSuffix(, "()")
	if  := strings.Index(, ".");  != -1 {
		return [+1:]
	}
	return 
}

func printDefault( io.Writer,  string,  string,  string) {
	 = strings.TrimSpace()
	if len() > 0 {
		fmt.Fprintf(, "%s%s '%s'\n", , , )
	} else {
		fmt.Fprintf(, "%s%s\n", , )
	}
}

func getListFlags( ListType) string {
	var  string
	if &ListTypeOrdered != 0 {
		 += "ordered "
	}
	if &ListTypeDefinition != 0 {
		 += "definition "
	}
	if &ListTypeTerm != 0 {
		 += "term "
	}
	if &ListItemContainsBlock != 0 {
		 += "has_block "
	}
	if &ListItemBeginningOfList != 0 {
		 += "start "
	}
	if &ListItemEndOfList != 0 {
		 += "end "
	}
	 = strings.TrimSpace()
	return 
}

func printRecur( io.Writer,  Node,  string,  int) {
	if  == nil {
		return
	}
	 := strings.Repeat(, )

	 := shortenString(getContent(), 40)
	 := getNodeType()
	switch v := .(type) {
	case *Link:
		 := "url=" + string(.Destination)
		printDefault(, , , )
	case *Image:
		 := "url=" + string(.Destination)
		printDefault(, , , )
	case *List:
		if .Start > 1 {
			 += fmt.Sprintf("start=%d ", .Start)
		}
		if .Tight {
			 += "tight "
		}
		if .IsFootnotesList {
			 += "footnotes "
		}
		 := getListFlags(.ListFlags)
		if len() > 0 {
			 += "flags=" +  + " "
		}
		printDefault(, , , )
	case *ListItem:
		if .Tight {
			 += "tight "
		}
		if .IsFootnotesList {
			 += "footnotes "
		}
		 := getListFlags(.ListFlags)
		if len() > 0 {
			 += "flags=" +  + " "
		}
		printDefault(, , , )
	case *CodeBlock:
		printDefault(, ,  + ":" + string(.Info), )
	default:
		printDefault(, , , )
	}
	for ,  := range .GetChildren() {
		(, , , +1)
	}
}