// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package html

import (
	
)

// A NodeType is the type of a Node.
type NodeType uint32

const (
	ErrorNode NodeType = iota
	TextNode
	DocumentNode
	ElementNode
	CommentNode
	DoctypeNode
	// RawNode nodes are not returned by the parser, but can be part of the
	// Node tree passed to func Render to insert raw HTML (without escaping).
	// If so, this package makes no guarantee that the rendered HTML is secure
	// (from e.g. Cross Site Scripting attacks) or well-formed.
	RawNode
	scopeMarkerNode
)

// Section 12.2.4.3 says "The markers are inserted when entering applet,
// object, marquee, template, td, th, and caption elements, and are used
// to prevent formatting from "leaking" into applet, object, marquee,
// template, td, th, and caption elements".
var scopeMarker = Node{Type: scopeMarkerNode}

// A Node consists of a NodeType and some Data (tag name for element nodes,
// content for text) and are part of a tree of Nodes. Element nodes may also
// have a Namespace and contain a slice of Attributes. Data is unescaped, so
// that it looks like "a<b" rather than "a&lt;b". For element nodes, DataAtom
// is the atom for Data, or zero if Data is not a known tag name.
//
// An empty Namespace implies a "http://www.w3.org/1999/xhtml" namespace.
// Similarly, "math" is short for "http://www.w3.org/1998/Math/MathML", and
// "svg" is short for "http://www.w3.org/2000/svg".
type Node struct {
	Parent, FirstChild, LastChild, PrevSibling, NextSibling *Node

	Type      NodeType
	DataAtom  atom.Atom
	Data      string
	Namespace string
	Attr      []Attribute
}

// InsertBefore inserts newChild as a child of n, immediately before oldChild
// in the sequence of n's children. oldChild may be nil, in which case newChild
// is appended to the end of n's children.
//
// It will panic if newChild already has a parent or siblings.
func ( *Node) (,  *Node) {
	if .Parent != nil || .PrevSibling != nil || .NextSibling != nil {
		panic("html: InsertBefore called for an attached child Node")
	}
	var ,  *Node
	if  != nil {
		,  = .PrevSibling, 
	} else {
		 = .LastChild
	}
	if  != nil {
		.NextSibling = 
	} else {
		.FirstChild = 
	}
	if  != nil {
		.PrevSibling = 
	} else {
		.LastChild = 
	}
	.Parent = 
	.PrevSibling = 
	.NextSibling = 
}

// AppendChild adds a node c as a child of n.
//
// It will panic if c already has a parent or siblings.
func ( *Node) ( *Node) {
	if .Parent != nil || .PrevSibling != nil || .NextSibling != nil {
		panic("html: AppendChild called for an attached child Node")
	}
	 := .LastChild
	if  != nil {
		.NextSibling = 
	} else {
		.FirstChild = 
	}
	.LastChild = 
	.Parent = 
	.PrevSibling = 
}

// RemoveChild removes a node c that is a child of n. Afterwards, c will have
// no parent and no siblings.
//
// It will panic if c's parent is not n.
func ( *Node) ( *Node) {
	if .Parent !=  {
		panic("html: RemoveChild called for a non-child Node")
	}
	if .FirstChild ==  {
		.FirstChild = .NextSibling
	}
	if .NextSibling != nil {
		.NextSibling.PrevSibling = .PrevSibling
	}
	if .LastChild ==  {
		.LastChild = .PrevSibling
	}
	if .PrevSibling != nil {
		.PrevSibling.NextSibling = .NextSibling
	}
	.Parent = nil
	.PrevSibling = nil
	.NextSibling = nil
}

// reparentChildren reparents all of src's child nodes to dst.
func reparentChildren(,  *Node) {
	for {
		 := .FirstChild
		if  == nil {
			break
		}
		.RemoveChild()
		.AppendChild()
	}
}

// clone returns a new node with the same type, data and attributes.
// The clone has no parent, no siblings and no children.
func ( *Node) () *Node {
	 := &Node{
		Type:     .Type,
		DataAtom: .DataAtom,
		Data:     .Data,
		Attr:     make([]Attribute, len(.Attr)),
	}
	copy(.Attr, .Attr)
	return 
}

// nodeStack is a stack of nodes.
type nodeStack []*Node

// pop pops the stack. It will panic if s is empty.
func ( *nodeStack) () *Node {
	 := len(*)
	 := (*)[-1]
	* = (*)[:-1]
	return 
}

// top returns the most recently pushed node, or nil if s is empty.
func ( *nodeStack) () *Node {
	if  := len(*);  > 0 {
		return (*)[-1]
	}
	return nil
}

// index returns the index of the top-most occurrence of n in the stack, or -1
// if n is not present.
func ( *nodeStack) ( *Node) int {
	for  := len(*) - 1;  >= 0; -- {
		if (*)[] ==  {
			return 
		}
	}
	return -1
}

// contains returns whether a is within s.
func ( *nodeStack) ( atom.Atom) bool {
	for ,  := range * {
		if .DataAtom ==  && .Namespace == "" {
			return true
		}
	}
	return false
}

// insert inserts a node at the given index.
func ( *nodeStack) ( int,  *Node) {
	(*) = append(*, nil)
	copy((*)[+1:], (*)[:])
	(*)[] = 
}

// remove removes a node from the stack. It is a no-op if n is not present.
func ( *nodeStack) ( *Node) {
	 := .index()
	if  == -1 {
		return
	}
	copy((*)[:], (*)[+1:])
	 := len(*) - 1
	(*)[] = nil
	* = (*)[:]
}

type insertionModeStack []insertionMode

func ( *insertionModeStack) () ( insertionMode) {
	 := len(*)
	 = (*)[-1]
	* = (*)[:-1]
	return 
}

func ( *insertionModeStack) () insertionMode {
	if  := len(*);  > 0 {
		return (*)[-1]
	}
	return nil
}