package templates

import scala.util.{Success, Try}
import scala.xml.transform.{RewriteRule, RuleTransformer}
import scala.xml._

abstract class Template(protected[this] val source: Node) {
  protected[this] val msgNotFound = "Not found"

  protected[this] def get(content: NodeSeq, attr: String = null, idx: Int = 0): Text =
    Try { content(idx) } match {
      case Success(v) if attr != null => v.attribute(attr) match {
        case None => Text(msgNotFound)
        case o => Text(o.get.text)
      }
      case Success(v) => Text(v.text)
      case _ => Text(msgNotFound)
  }

  def template: Node

  def isStraight: Boolean

  def render: Node = {
    def attrIsEmpty(n: Node): Boolean = n match {
      case v: Elem if v.child.isEmpty => v.attributes.isEmpty
      case v => v.attributes.isEmpty && v.child.forall(attrIsEmpty)
    }

    val rule1: RewriteRule = new RewriteRule {
      override def transform(n: Node): NodeSeq = n match {
        case v: Elem if v.attributes.nonEmpty && v.attributes.value.text.contains(msgNotFound) =>
          v.copy(attributes = v.attributes.filter(_.value.text != msgNotFound))
        case _ => n
      }
    }

    val rule2: RewriteRule = new RewriteRule {
      override def transform(n: Node): NodeSeq = n match {
        case v if v.text == msgNotFound =>
          NodeSeq.Empty
        case v: Elem if attrIsEmpty(v) && v.text.filterNot(_.isWhitespace).isEmpty =>
          NodeSeq.Empty
        case _ => n
      }
    }

    val rt1 = new RuleTransformer(rule1)
    val rt2 = new RuleTransformer(rule2)

    rt2.transform(rt1.transform(template)).head
  }

  def info(msg: String): String = msg
 }

object Template {
  def apply(source: Node)(implicit templateFactory: Node => Template): Template = templateFactory(source)
}


