package parser

import (
	
	

	
	
	
)

// A DelimiterProcessor interface provides a set of functions about
// Delimiter nodes.
type DelimiterProcessor interface {
	// IsDelimiter returns true if given character is a delimiter, otherwise false.
	IsDelimiter(byte) bool

	// CanOpenCloser returns true if given opener can close given closer, otherwise false.
	CanOpenCloser(opener, closer *Delimiter) bool

	// OnMatch will be called when new matched delimiter found.
	// OnMatch should return a new Node correspond to the matched delimiter.
	OnMatch(consumes int) ast.Node
}

// A Delimiter struct represents a delimiter like '*' of the Markdown text.
type Delimiter struct {
	ast.BaseInline

	Segment text.Segment

	// CanOpen is set true if this delimiter can open a span for a new node.
	// See https://spec.commonmark.org/0.30/#can-open-emphasis for details.
	CanOpen bool

	// CanClose is set true if this delimiter can close a span for a new node.
	// See https://spec.commonmark.org/0.30/#can-open-emphasis for details.
	CanClose bool

	// Length is a remaining length of this delimiter.
	Length int

	// OriginalLength is a original length of this delimiter.
	OriginalLength int

	// Char is a character of this delimiter.
	Char byte

	// PreviousDelimiter is a previous sibling delimiter node of this delimiter.
	PreviousDelimiter *Delimiter

	// NextDelimiter is a next sibling delimiter node of this delimiter.
	NextDelimiter *Delimiter

	// Processor is a DelimiterProcessor associated with this delimiter.
	Processor DelimiterProcessor
}

// Inline implements Inline.Inline.
func ( *Delimiter) () {}

// Dump implements Node.Dump.
func ( *Delimiter) ( []byte,  int) {
	fmt.Printf("%sDelimiter: \"%s\"\n", strings.Repeat("    ", ), string(.Text()))
}

var kindDelimiter = ast.NewNodeKind("Delimiter")

// Kind implements Node.Kind.
func ( *Delimiter) () ast.NodeKind {
	return kindDelimiter
}

// Text implements Node.Text.
func ( *Delimiter) ( []byte) []byte {
	return .Segment.Value()
}

// ConsumeCharacters consumes delimiters.
func ( *Delimiter) ( int) {
	.Length -= 
	.Segment = .Segment.WithStop(.Segment.Start + .Length)
}

// CalcComsumption calculates how many characters should be used for opening
// a new span correspond to given closer.
func ( *Delimiter) ( *Delimiter) int {
	if (.CanClose || .CanOpen) && (.OriginalLength+.OriginalLength)%3 == 0 && .OriginalLength%3 != 0 {
		return 0
	}
	if .Length >= 2 && .Length >= 2 {
		return 2
	}
	return 1
}

// NewDelimiter returns a new Delimiter node.
func (,  bool,  int,  byte,  DelimiterProcessor) *Delimiter {
	 := &Delimiter{
		BaseInline:        ast.BaseInline{},
		CanOpen:           ,
		CanClose:          ,
		Length:            ,
		OriginalLength:    ,
		Char:              ,
		PreviousDelimiter: nil,
		NextDelimiter:     nil,
		Processor:         ,
	}
	return 
}

// ScanDelimiter scans a delimiter by given DelimiterProcessor.
func ( []byte,  rune,  int,  DelimiterProcessor) *Delimiter {
	 := 0
	 := []
	 := 
	if !.IsDelimiter() {
		return nil
	}
	for ;  < len() &&  == []; ++ {
	}
	if ( - ) >=  {
		 := rune(' ')
		if  != len() {
			 = util.ToRune(, )
		}

		var ,  bool
		 := util.IsPunctRune()
		 := util.IsSpaceRune()
		 := util.IsPunctRune()
		 := util.IsSpaceRune()

		 := ! &&
			(! ||  || )
		 := ! &&
			(! ||  || )

		if [] == '_' {
			 =  && (! || )
			 =  && (! || )
		} else {
			 = 
			 = 
		}
		return NewDelimiter(, , -, , )
	}
	return nil
}

// ProcessDelimiters processes the delimiter list in the context.
// Processing will be stop when reaching the bottom.
//
// If you implement an inline parser that can have other inline nodes as
// children, you should call this function when nesting span has closed.
func ( ast.Node,  Context) {
	 := .LastDelimiter()
	if  == nil {
		return
	}
	var  *Delimiter
	if  != nil {
		if  !=  {
			for  := .PreviousSibling();  != nil &&  != ; {
				if ,  := .(*Delimiter);  {
					 = 
				}
				 = .PreviousSibling()
			}
		}
	} else {
		 = .FirstDelimiter()
	}
	if  == nil {
		.ClearDelimiters()
		return
	}
	for  != nil {
		if !.CanClose {
			 = .NextDelimiter
			continue
		}
		 := 0
		 := false
		 := false
		var  *Delimiter
		for  = .PreviousDelimiter;  != nil &&  != ;  = .PreviousDelimiter {
			if .CanOpen && .Processor.CanOpenCloser(, ) {
				 = true
				 = .CalcComsumption()
				if  > 0 {
					 = true
					break
				}
			}
		}
		if ! {
			 := .NextDelimiter
			if ! && !.CanOpen {
				.RemoveDelimiter()
			}
			 = 
			continue
		}
		.ConsumeCharacters()
		.ConsumeCharacters()

		 := .Processor.OnMatch()

		 := .Parent()
		 := .NextSibling()

		for  != nil &&  !=  {
			 := .NextSibling()
			.AppendChild(, )
			 = 
		}
		.InsertAfter(, , )

		for  := .NextDelimiter;  != nil &&  != ; {
			 := .NextDelimiter
			.RemoveDelimiter()
			 = 
		}

		if .Length == 0 {
			.RemoveDelimiter()
		}

		if .Length == 0 {
			 := .NextDelimiter
			.RemoveDelimiter()
			 = 
		}
	}
	.ClearDelimiters()
}