package parser

import (
	

	
	
	
)

type fencedCodeBlockParser struct {
}

var defaultFencedCodeBlockParser = &fencedCodeBlockParser{}
NewFencedCodeBlockParser returns a new BlockParser that parses fenced code blocks.
func () BlockParser {
	return defaultFencedCodeBlockParser
}

type fenceData struct {
	char   byte
	indent int
	length int
	node   ast.Node
}

var fencedCodeBlockInfoKey = NewContextKey()

func ( *fencedCodeBlockParser) () []byte {
	return []byte{'~', '`'}
}

func ( *fencedCodeBlockParser) ( ast.Node,  text.Reader,  Context) (ast.Node, State) {
	,  := .PeekLine()
	 := .BlockOffset()
	if  < 0 || ([] != '`' && [] != '~') {
		return nil, NoChildren
	}
	 := 
	 := []
	 := 
	for ;  < len() && [] == ; ++ {
	}
	 :=  - 
	if  < 3 {
		return nil, NoChildren
	}
	var  *ast.Text
	if  < len()-1 {
		 := [:]
		 := util.TrimLeftSpaceLength()
		 := util.TrimRightSpaceLength()
		if  < len()- {
			,  := .Start-.Padding++, .Stop-
			 := [ : len()-]
			if  == '`' && bytes.IndexByte(, '`') > -1 {
				return nil, NoChildren
			} else if  !=  {
				 = ast.NewTextSegment(text.NewSegment(, ))
			}
		}
	}
	 := ast.NewFencedCodeBlock()
	.Set(fencedCodeBlockInfoKey, &fenceData{, , , })
	return , NoChildren

}

func ( *fencedCodeBlockParser) ( ast.Node,  text.Reader,  Context) State {
	,  := .PeekLine()
	 := .Get(fencedCodeBlockInfoKey).(*fenceData)
if code block line starts with a tab, keep a tab as it is.
	if .Padding != 0 {
		preserveLeadingTabInCodeBlock(&, , .indent)
	}
	,  := util.IndentWidth(, .LineOffset())
	if  < 4 {
		 := 
		for ;  < len() && [] == .char; ++ {
		}
		 :=  - 
		if  >= .length && util.IsBlank([:]) {
			 := 1
			if [len()-1] != '\n' {
				 = 0
			}
			.Advance(.Stop - .Start -  - .Padding)
			return Close
		}
	}
	,  := util.DedentPositionPadding(, .LineOffset(), .Padding, .indent)

	 := text.NewSegmentPadding(.Start+, .Stop, )
	.Lines().Append()
	.AdvanceAndSetPadding(.Stop-.Start--1, )
	return Continue | NoChildren
}

func ( *fencedCodeBlockParser) ( ast.Node,  text.Reader,  Context) {
	 := .Get(fencedCodeBlockInfoKey).(*fenceData)
	if .node ==  {
		.Set(fencedCodeBlockInfoKey, nil)
	}
}

func ( *fencedCodeBlockParser) () bool {
	return true
}

func ( *fencedCodeBlockParser) () bool {
	return false