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 ( 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 ( Context,  *linkLabelState) {
	 := .Get(linkLabelStateKey)
	var  *linkLabelState
	if  == nil {
		 = 
		.First = 
		.Last = 
		.Set(linkLabelStateKey, )
	} else {
		 = .(*linkLabelState)
		 := .Last
		.Last = 
		.Next = 
		.Prev = 
	}
}

func ( 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)
			.Set(linkBottom, .LastDelimiter())
			return processLinkLabelOpen(, .Start+1, true, )
		}
		return nil
	}
	if [0] == '[' {
		.Set(linkBottom, .LastDelimiter())
		return processLinkLabelOpen(, .Start, false, )
	}
line[0] == ']'
	 := .Get(linkLabelStateKey)
	if  == nil {
		return nil
	}
	 := .(*linkLabelState).Last
	if  == nil {
		return nil
	}
	.Advance(1)
	removeLinkLabelState(, )
	if .containsLink() { // a link in a link text is not allowed
		ast.MergeOrReplaceTextSegment(.Parent(), , .Segment)
		return nil
	}

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

maybe shortcut reference link
		.SetPosition(, )
		 := text.NewSegment(.Segment.Stop, .Start)
		 := .Value()
		,  := .Reference(util.ToLinkReference())
		if ! {
			ast.MergeOrReplaceTextSegment(.Parent(), , .Segment)
			return nil
		}
		 = ast.NewLink()
		.processLinkLabel(, , , )
		.Title = .Title()
		.Destination = .Destination()
	}
	if .IsImage {
		.Parent().RemoveChild(.Parent(), )
		return ast.NewImage()
	}
	.Parent().RemoveChild(.Parent(), )
	return 
}

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

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

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

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

	.Advance( + 1)
	 := .WithStop(.Start + )
	 := .Value()
	if util.IsBlank() { // collapsed reference link
		 = text.NewSegment(.Segment.Stop, .Start-1)
		 = .Value()
	}

	,  := .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 ( 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 ( text.Reader) ([]byte, bool) {
	.SkipSpaces()
	 := .Peek()
	if  != '"' &&  != '\'' &&  != '(' {
		return nil, false
	}
	 := 
	if  == '(' {
		 = ')'
	}
	,  := .Position()
	var  []byte
	for  := 0; ; ++ {
		,  := .PeekLine()
		if  == nil {
			.SetPosition(, )
			return nil, false
		}
		 := 0
		if  == 0 {
			 = 1
		}
		 := util.FindClosure([:], , , false, true)
		if  < 0 {
			 = append(, [:]...)
			.AdvanceLine()
			continue
		}
		 +=  + 1 // 1: closer
		.Advance()
		if  == 0 { // avoid allocating new slice
			return [ : -1], true
		}
		return append(, [:-1]...), true
	}
}

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