package scales.xml.parser.strategies
import scales.xml._
import scales.utils.collection.{Tree, ImmutableArrayProxy}
import scales.xml.impl.{NotFromParser, IsFromParser, FromParser}
import ImmutableArrayProxy.one
import impl.TreeProxies
 
trait TreeOptimisation[TOKEN <: OptimisationToken] extends PathOptimisationStrategy[TOKEN] {
  def newTree( elem : Elem, children : XmlChildren, token : TOKEN ) : XmlTree
  final override def elementEnd( xml : TreeProxies, token : TOKEN ) {
    import ScalesXml.xmlCBF
    val l = xml.current
    val nt = newTree(l.elem, l.builder.result, token)
    val d = xml.depth
    val nd = d - 1
    if (d > 0) {
      xml.depth = nd
      val c = xml.proxy( nd )
      xml.current = c
      c.builder.+=(nt)
    } else {
      xml.rootTree = nt 
      xml.depth = nd
    }
  }
}
abstract class NameValue(val name : QName, val text : String) extends Tree[XmlItem, Elem, XCC] {
  def section : Elem
  def children : XmlChildren = one(Text(text))
  def copy( section : Elem = section, children : XmlChildren = children) : Tree[XmlItem, Elem, XCC] = {
    
    import ScalesXml.fromParserDefault
    LazyOptimisedTree(section, children)
  }
}
class ElemValue(val section : Elem, val text : String) extends Tree[XmlItem, Elem, XCC] {
  def children : XmlChildren = one(Text(text))
  def copy( section : Elem = section, children : XmlChildren = children) : Tree[XmlItem, Elem, XCC] = {
    
    import ScalesXml.fromParserDefault
    LazyOptimisedTree(section, children)
  }
}
 
object LazyOptimisedTree {
   
  def apply( section : Elem, children : XmlChildren ) ( implicit fromParser : FromParser ) : XmlTree = 
    if (children.isEmpty)
      Tree(section, children)
    else {
      val head = children.head
      if (head.isLeft) {
	val left = head.getLeft
	if (left.isInstanceOf[Text] && children.size == 1) {
	  if (section.attributes.isEmpty && section.namespaces.isEmpty)
	    newNameValue(section.name, left.value)
	  else
	    new ElemValue(section, left.value)
	} else Tree(section, children)
      } else Tree(section, children)
    }
  
  def newNameValue( iname : QName, itext : String ) ( implicit fromParser : FromParser ) : NameValue = 
    if (fromParser eq NotFromParser)
      new NameValue(iname, itext) {
	
	def section : Elem = Elem(name)(NotFromParser) 
      }
    else
      new NameValue(iname, itext) {
	
	def section : Elem = Elem(name)(IsFromParser) 
      }
}
 
object QNameTreeOptimisation extends TreeOptimisation[QNameToken] with QNameOptimisationT[QNameToken] with QNameTokenF {
  def newTree( elem : Elem, children : XmlChildren, token : QNameToken ) : XmlTree =
    LazyOptimisedTree( elem, children )(IsFromParser)
}
object QNameElemTreeOptimisation extends PathOptimisationStrategy[ElemToken] with ElemQNameOptimisationT[ElemToken] with TreeOptimisation[ElemToken] with ElemTokenF {
  
  def newTree( elem : Elem, children : XmlChildren, token : ElemToken ) : XmlTree =
    LazyOptimisedTree( elem, children )(IsFromParser)
}