/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.zeppelin.display.angular

import java.io.PrintStream

import org.apache.zeppelin.annotation.ZeppelinApi
import org.apache.zeppelin.display.{AngularObjectWatcher, AngularObject}
import org.apache.zeppelin.interpreter.{InterpreterResult, InterpreterContext}

import scala.xml._

/**
  * Element that binded to Angular object
  */
abstract class AbstractAngularElem(val interpreterContext: InterpreterContext,
                                   val modelName: String,
                                   val angularObjects: Map[String, AngularObject[Any]],
                                   prefix: String,
                                   label: String,
                                   attributes1: MetaData,
                                   scope: NamespaceBinding,
                                   minimizeEmpty: Boolean,
                                   child: Node*)
  extends Elem(prefix, label, attributes1, scope, minimizeEmpty, child:_*) {

  val uniqueId = java.util.UUID.randomUUID.toString.replaceAll("-", "_")

  /**
    * On click element
 *
    * @param callback
    * @return
    */
  @ZeppelinApi
  def onClick(callback: () => Unit): AbstractAngularElem = {
    onEvent("ng-click", callback)
  }

  /**
    * On
 *
    * @param callback
    * @return
    */
  @ZeppelinApi
  def onChange(callback: () => Unit): AbstractAngularElem = {
    onEvent("ng-change", callback)
  }

  /**
    * Bind angularObject to ng-model directive
 *
    * @param name name of angularObject
    * @param value initialValue
    * @return
    */
  @ZeppelinApi
  def model(name: String, value: Any): AbstractAngularElem = {
    val registry = interpreterContext.getAngularObjectRegistry

    // create AngularFunction in current paragraph
    val elem = this % Attribute(None, "ng-model",
      Text(s"${name}"),
      Null)

    val angularObject = addAngularObject(name, value)
      .asInstanceOf[AngularObject[Any]]

    newElem(
      interpreterContext,
      name,
      angularObjects + ((name, angularObject)),
      elem)
  }


  @ZeppelinApi
  def model(name: String): AbstractAngularElem = {
    val registry = interpreterContext.getAngularObjectRegistry

    // create AngularFunction in current paragraph
    val elem = this % Attribute(None, "ng-model",
      Text(s"${name}"),
      Null)

    newElem(
      interpreterContext,
      name,
      angularObjects,
      elem)
  }

  /**
    * Retrieve value of model
    *
    * @return
    */
  @ZeppelinApi
  def model(): Any = {
    if (angularObjects.contains(modelName)) {
      angularObjects(modelName).get()
    } else {
      None
    }
  }

  /**
    *
    * @param eventName angular directive like ng-click, ng-change, etc.
    * @return
    */
  @ZeppelinApi
  def onEvent(eventName: String, callback: () => Unit): AbstractAngularElem = {
    val registry = interpreterContext.getAngularObjectRegistry

    // create AngularFunction in current paragraph
    val functionName = eventName.replaceAll("-", "_") + "_" + uniqueId
    val elem = this % Attribute(None, eventName,
      Text(s"${functionName}=${functionName} + 1"),
      Null)

    val angularObject = addAngularObject(functionName, 0)

    angularObject.addWatcher(new AngularObjectWatcher(interpreterContext) {
      override def watch(oldObject: scala.Any, newObject: scala.Any, context: InterpreterContext)
      :Unit = {
        InterpreterContext.set(interpreterContext)
        callback()
      }
    })

    newElem(
      interpreterContext,
      modelName,
      angularObjects + ((eventName, angularObject)),
      elem)
  }

  protected def addAngularObject(name: String, value: Any): AngularObject[Any]

  protected def newElem(interpreterContext: InterpreterContext,
                        name: String,
                        angularObjects: Map[String, AngularObject[Any]],
                        elem: scala.xml.Elem): AbstractAngularElem

  /**
    * disassociate this element and it's child from front-end
    * by removing angularobject
    */
  @ZeppelinApi
  def disassociate() = {
    remove(this)
  }

  /**
    * Remove all angularObject recursively
    *
    * @param node
    */
  private def remove(node: Node): Unit = {
    if (node.isInstanceOf[AbstractAngularElem]) {
      node.asInstanceOf[AbstractAngularElem].angularObjects.values.foreach{ ao =>
        interpreterContext.getAngularObjectRegistry.remove(ao.getName, ao.getNoteId, ao
          .getParagraphId)
      }
    }

    node.child.foreach(remove _)
  }

  /**
    * Print into provided print stream
    *
    * @return
    */
  @ZeppelinApi
  def display(out: java.io.PrintStream): Unit = {
    out.print(this.toString)
    out.flush()
  }

  /**
    * Print into InterpreterOutput
    */
  @ZeppelinApi
  def display(): Unit = {
    val out = interpreterContext.out
    out.setType(InterpreterResult.Type.ANGULAR)
    out.write(this.toString())
    out.flush()
  }
}

