package parser

import (
	
	

	
	
	
)

var linkLabelStateKey = NewContextKey()

type linkLabelState struct {
	ast.BaseInline

	Segment text.Segment

	IsImage bool

	Prev *linkLabelState

	Next *linkLabelState

	First *linkLabelState

	Last *linkLabelState
}

func newLinkLabelState( text.Segment,  bool) *linkLabelState {
	return &linkLabelState{
		Segment: ,
		IsImage: ,
	}
}

func ( *linkLabelState) ( []byte) []byte {
	return .Segment.Value()
}

func ( *linkLabelState) ( []byte,  int) {
	fmt.Printf("%slinkLabelState: \"%s\"\n", strings.Repeat("    ", ), .Text())
}

var kindLinkLabelState = ast.NewNodeKind("LinkLabelState")

func ( *linkLabelState) () ast.NodeKind {
	return kindLinkLabelState
}

func linkLabelStateLength( *linkLabelState) int {
	if  == nil || .Last == nil || .First == nil {
		return 0
	}
	return .Last.Segment.Stop - .First.Segment.Start
}

func pushLinkLabelState( Context,  *linkLabelState) {
	 := .Get(linkLabelStateKey)
	var  *linkLabelState
	if  == nil {
		 = 
		.First = 
		.Last = 
		.Set(linkLabelStateKey, )
	} else {
		 = .(*linkLabelState)
		 := .Last
		.Last = 
		.Next = 
		.Prev = 
	}
}

func removeLinkLabelState( Context,  *linkLabelState) {
	 := .Get(linkLabelStateKey)
	var  *linkLabelState
	if  == nil {
		return
	}
	 = .(*linkLabelState)

	if .Prev == nil {
		 = .Next
		if  != nil {
			.First = 
			.Last = .Last
			.Prev = nil
			.Set(linkLabelStateKey, )
		} else {
			.Set(linkLabelStateKey, nil)
		}
	} else {
		.Prev.Next = .Next
		if .Next != nil {
			.Next.Prev = .Prev
		}
	}
	if  != nil && .Next == nil {
		.Last = .Prev
	}
	.Next = nil
	.Prev = nil
	.First = nil
	.Last = nil
}

type linkParser struct {
}

var defaultLinkParser = &linkParser{}

// NewLinkParser return a new InlineParser that parses links.
func () InlineParser {
	return defaultLinkParser
}

func ( *linkParser) () []byte {
	return []byte{'!', '[', ']'}
}

var linkBottom = NewContextKey()

func ( *linkParser) ( ast.Node,  text.Reader,  Context) ast.Node {
	,  := .PeekLine()
	if [0] == '!' {
		if len() > 1 && [1] == '[' {
			.Advance(1)
			pushLinkBottom()
			return processLinkLabelOpen(, .Start+1, true, )
		}
		return nil
	}
	if [0] == '[' {
		pushLinkBottom()
		return processLinkLabelOpen(, .Start, false, )
	}

	// line[0] == ']'
	 := .Get(linkLabelStateKey)
	if  == nil {
		return nil
	}
	 := .(*linkLabelState).Last
	if  == nil {
		_ = popLinkBottom()
		return nil
	}
	.Advance(1)
	removeLinkLabelState(, )
	// CommonMark spec says:
	//  > A link label can have at most 999 characters inside the square brackets.
	if linkLabelStateLength(.(*linkLabelState)) > 998 {
		ast.MergeOrReplaceTextSegment(.Parent(), , .Segment)
		_ = popLinkBottom()
		return nil
	}

	if !.IsImage && .containsLink() { // a link in a link text is not allowed
		ast.MergeOrReplaceTextSegment(.Parent(), , .Segment)
		_ = popLinkBottom()
		return nil
	}

	 := .Peek()
	,  := .Position()
	var  *ast.Link
	var  bool
	if  == '(' { // normal link
		 = .parseLink(, , , )
	} else if  == '[' { // reference link
		,  = .parseReferenceLink(, , , )
		if  == nil &&  {
			ast.MergeOrReplaceTextSegment(.Parent(), , .Segment)
			_ = popLinkBottom()
			return nil
		}
	}

	if  == nil {
		// maybe shortcut reference link
		.SetPosition(, )
		 := text.NewSegment(.Segment.Stop, .Start)
		 := .Value()
		// CommonMark spec says:
		//  > A link label can have at most 999 characters inside the square brackets.
		if len() > 999 {
			ast.MergeOrReplaceTextSegment(.Parent(), , .Segment)
			_ = popLinkBottom()
			return nil
		}

		,  := .Reference(util.ToLinkReference())
		if ! {
			ast.MergeOrReplaceTextSegment(.Parent(), , .Segment)
			_ = popLinkBottom()
			return nil
		}
		 = ast.NewLink()
		.processLinkLabel(, , , )
		.Title = .Title()
		.Destination = .Destination()
	}
	if .IsImage {
		.Parent().RemoveChild(.Parent(), )
		return ast.NewImage()
	}
	.Parent().RemoveChild(.Parent(), )
	return 
}

func ( *linkParser) ( ast.Node) bool {
	if  == nil {
		return false
	}
	for  := ;  != nil;  = .NextSibling() {
		if ,  := .(*ast.Link);  {
			return true
		}
		if .(.FirstChild()) {
			return true
		}
	}
	return false
}

func processLinkLabelOpen( text.Reader,  int,  bool,  Context) *linkLabelState {
	 := 
	if  {
		--
	}
	 := newLinkLabelState(text.NewSegment(, +1), )
	pushLinkLabelState(, )
	.Advance(1)
	return 
}

func ( *linkParser) ( ast.Node,  *ast.Link,  *linkLabelState,  Context) {
	 := popLinkBottom()
	ProcessDelimiters(, )
	for  := .NextSibling();  != nil; {
		 := .NextSibling()
		.RemoveChild(, )
		.AppendChild(, )
		 = 
	}
}

var linkFindClosureOptions text.FindClosureOptions = text.FindClosureOptions{
	Nesting: false,
	Newline: true,
	Advance: true,
}

func ( *linkParser) ( ast.Node,  *linkLabelState,
	 text.Reader,  Context) (*ast.Link, bool) {
	,  := .Position()
	.Advance(1) // skip '['
	,  := .FindClosure('[', ']', linkFindClosureOptions)
	if ! {
		return nil, false
	}

	var  []byte
	if .Len() == 1 { // avoid allocate a new byte slice
		 = .Value(.At(0))
	} else {
		 = []byte{}
		for  := 0;  < .Len(); ++ {
			 := .At()
			 = append(, .Value()...)
		}
	}
	if util.IsBlank() { // collapsed reference link
		 := text.NewSegment(.Segment.Stop, .Start-1)
		 = .Value()
	}
	// CommonMark spec says:
	//  > A link label can have at most 999 characters inside the square brackets.
	if len() > 999 {
		return nil, true
	}

	,  := .Reference(util.ToLinkReference())
	if ! {
		return nil, true
	}

	 := ast.NewLink()
	.processLinkLabel(, , , )
	.Title = .Title()
	.Destination = .Destination()
	return , true
}

func ( *linkParser) ( ast.Node,  *linkLabelState,  text.Reader,  Context) *ast.Link {
	.Advance(1) // skip '('
	.SkipSpaces()
	var  []byte
	var  []byte
	var  bool
	if .Peek() == ')' { // empty link like '[link]()'
		.Advance(1)
	} else {
		,  = parseLinkDestination()
		if ! {
			return nil
		}
		.SkipSpaces()
		if .Peek() == ')' {
			.Advance(1)
		} else {
			,  = parseLinkTitle()
			if ! {
				return nil
			}
			.SkipSpaces()
			if .Peek() == ')' {
				.Advance(1)
			} else {
				return nil
			}
		}
	}

	 := ast.NewLink()
	.processLinkLabel(, , , )
	.Destination = 
	.Title = 
	return 
}

func parseLinkDestination( text.Reader) ([]byte, bool) {
	.SkipSpaces()
	,  := .PeekLine()
	if .Peek() == '<' {
		 := 1
		for  < len() {
			 := []
			if  == '\\' &&  < len()-1 && util.IsPunct([+1]) {
				 += 2
				continue
			} else if  == '>' {
				.Advance( + 1)
				return [1:], true
			}
			++
		}
		return nil, false
	}
	 := 0
	 := 0
	for  < len() {
		 := []
		if  == '\\' &&  < len()-1 && util.IsPunct([+1]) {
			 += 2
			continue
		} else if  == '(' {
			++
		} else if  == ')' {
			--
			if  < 0 {
				break
			}
		} else if util.IsSpace() {
			break
		}
		++
	}
	.Advance()
	return [:], len([:]) != 0
}

func parseLinkTitle( text.Reader) ([]byte, bool) {
	.SkipSpaces()
	 := .Peek()
	if  != '"' &&  != '\'' &&  != '(' {
		return nil, false
	}
	 := 
	if  == '(' {
		 = ')'
	}
	.Advance(1)
	,  := .FindClosure(, , linkFindClosureOptions)
	if  {
		if .Len() == 1 {
			return .Value(.At(0)), true
		}
		var  []byte
		for  := 0;  < .Len(); ++ {
			 := .At()
			 = append(, .Value()...)
		}
		return , true
	}
	return nil, false
}

func pushLinkBottom( Context) {
	 := .Get(linkBottom)
	 := .LastDelimiter()
	if  == nil {
		.Set(linkBottom, )
		return
	}
	if ,  := .([]ast.Node);  {
		.Set(linkBottom, append(, ))
		return
	}
	.Set(linkBottom, []ast.Node{.(ast.Node), })
}

func popLinkBottom( Context) ast.Node {
	 := .Get(linkBottom)
	if  == nil {
		return nil
	}
	if ,  := .(ast.Node);  {
		.Set(linkBottom, nil)
		return 
	}
	 := .([]ast.Node)
	 := [len()-1]
	 := [0 : len()-1]
	switch len() {
	case 0:
		.Set(linkBottom, nil)
	case 1:
		.Set(linkBottom, [0])
	default:
		.Set(linkBottom, [0:len()-1])
	}
	return 
}

func ( *linkParser) ( ast.Node,  text.Reader,  Context) {
	.Set(linkBottom, nil)
	 := .Get(linkLabelStateKey)
	if  == nil {
		return
	}
	for  := .(*linkLabelState);  != nil; {
		 := .Next
		removeLinkLabelState(, )
		.Parent().ReplaceChild(.Parent(), , ast.NewTextSegment(.Segment))
		 = 
	}
}