package parser

import (
	
	
	
)

// isInclude parses {{...}}[...], that contains a path between the {{, the [...] syntax contains
// an address to select which lines to include. It is treated as an opaque string and just given
// to readInclude.
func ( *Parser) ( []byte) ( string,  []byte,  int) {
	 := skipCharN(, 0, ' ', 3) // start with up to 3 spaces
	if len([:]) < 3 {
		return "", nil, 0
	}
	if [] != '{' || [+1] != '{' {
		return "", nil, 0
	}
	 :=  + 2

	// find the end delimiter
	 = skipUntilChar(, , '}')
	if +1 >= len() {
		return "", nil, 0
	}
	 := 
	++
	if [] != '}' {
		return "", nil, 0
	}
	 = string([:])

	if +1 < len() && [+1] == '[' { // potential address specification
		 :=  + 2

		 = skipUntilChar(, , ']')
		if  >= len() {
			return "", nil, 0
		}
		 = [:]
		return , ,  + 1
	}

	return , ,  + 1
}

func ( *Parser) (,  string,  []byte) []byte {
	if .Opts.ReadIncludeFn != nil {
		return .Opts.ReadIncludeFn(, , )
	}

	return nil
}

// isCodeInclude parses <{{...}} which is similar to isInclude the returned bytes are, however wrapped in a code block.
func ( *Parser) ( []byte) ( string,  []byte,  int) {
	 := skipCharN(, 0, ' ', 3) // start with up to 3 spaces
	if len([:]) < 3 {
		return "", nil, 0
	}
	if [] != '<' {
		return "", nil, 0
	}
	 := 

	, ,  = .isInclude([+1:])
	if  == 0 {
		return "", nil, 0
	}
	return , ,  +  + 1
}

// readCodeInclude acts like include except the returned bytes are wrapped in a fenced code block.
func ( *Parser) (,  string,  []byte) []byte {
	 := .readInclude(, , )
	if  == nil {
		return nil
	}
	 := path.Ext()
	 := &bytes.Buffer{}
	.Write([]byte("```"))
	if  != "" { // starts with a dot
		.WriteString(" " + [1:] + "\n")
	} else {
		.WriteByte('\n')
	}
	.Write()
	.WriteString("```\n")
	return .Bytes()
}

// incStack hold the current stack of chained includes. Each value is the containing
// path of the file being parsed.
type incStack struct {
	stack []string
}

func newIncStack() *incStack {
	return &incStack{stack: []string{}}
}

// Push updates i with new.
func ( *incStack) ( string) {
	if path.IsAbs() {
		.stack = append(.stack, path.Dir())
		return
	}
	 := ""
	if len(.stack) > 0 {
		 = .stack[len(.stack)-1]
	}
	.stack = append(.stack, path.Dir(filepath.Join(, )))
}

// Pop pops the last value.
func ( *incStack) () {
	if len(.stack) == 0 {
		return
	}
	.stack = .stack[:len(.stack)-1]
}

func ( *incStack) () string {
	if len(.stack) == 0 {
		return ""
	}
	return .stack[len(.stack)-1]
}