package controllers

import play.api._
import play.api.mvc._

object Plugin extends Controller {
  def route(path: String) : Action[AnyContent] = Action {
    Ok("Done")
  }
}


package controllers

import org.mozilla.javascript.Context
import org.mozilla.javascript.Function
import org.mozilla.javascript.Scriptable
import play.api._
import play.api.mvc._

// FIXME: Move GamePlugin and its related classes, traits and objects to beyond package.
private trait GamePlugin {
  // FIXME: Pass request parameters along with path and
  // make it possible to return the result asynchronously.
  def handle(path: String): String
}

// FIXME: Handle script errors.
private object GamePlugin {
  def apply(): GamePlugin = {
    // FIXME: Don't hardcode plugin source code here.
    val source = "function handle(path) { return 'Hello ' + path; }"
    val cx: Context = Context.enter()
    try {
      val scope: Scriptable = cx.initStandardObjects()
      cx.evaluateString(scope, source, "source", 1, null)
      // FIXME: Don't hardcode the name of handler function.
      // FIXME: handler might be Scriptable.NOT_FOUND if there is no function named "handle".
      // Also, it might not be an instance of Function.
      val handler = scope.get("handle", scope).asInstanceOf[Function]
      new GamePluginImpl(scope, handler)
    } finally {
      Context.exit()
    }
  }

  private class GamePluginImpl(scope: Scriptable, handler: Function) extends GamePlugin {
    def handle(path: String): String = {
      val cx: Context = Context.enter()
      try {
        val args: Array[AnyRef] = Array(path)
        val result = handler.call(cx, scope, scope, args)
        result.toString
      } finally {
        Context.exit()
      }
    }
  }
}

object Plugin extends Controller {
  private val gamePlugin: GamePlugin = GamePlugin()

  def route(path: String) : Action[AnyContent] = Action { request =>
    val result = gamePlugin.handle(request.path)
    Ok(result)
  }
}


Implement a simple plugin system for game logic.
Implement a simple plugin system for game logic.

GameLogic allows Beyond users to write game logics in JavaScript. It accepts an
incoming request to the plugin path and returns a response.

This is a proof-of-concept implementation, so plugin path and scripts are all
hardcoded. Also there is no way to register a plugin. More patches will follow.
