/**
 * 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.esme.lib

import net.liftweb._
import http._
import js._
import js.jquery._
import http.jquery._
import JqJsCmds._
import JsCmds._ 
import SHtml._
import JE._

import sitemap._
import Loc._

import mapper._

import util._
import common._
import Helpers._

import widgets.autocomplete.AutoComplete

import org.apache.esme._
import model._
import org.apache.esme.actor.Distributor

import scala.xml._

import java.util.Date
import java.text.{DateFormat,SimpleDateFormat}

/**
 * Manage the sitemap and related snippets for Access Pools
 */
object AccessPoolMgr {
  val logger: Logger = Logger("org.apache.esme.lib.AccessPoolMgr")
  def loggedIn_? = User.loggedIn_?

  val ifIsLoggedIn = If(loggedIn_? _, strFuncToFailMsg(() => S.?("base_error_not_logged_in")))

  val menuItems =
  Menu(Loc("pools", new Link("pools" :: Nil, true)/*List("pools_view", "index")*/, S.?("base_pool_menu"), ifIsLoggedIn,
           Loc.Snippet("addPool", addPool),
           Loc.Snippet("editPool", editPool),
           Loc.Snippet("poolUsers", displayPoolUsers),
  		   Loc.Snippet("poolDetail", displayPoolDetail)//regist snippet for pool detail display
          ,Loc.Snippet("myPools", myPoolsWithRoles)          
  		)) ::
  Nil

  object updatePool extends RequestVar[() => JsCmd](() => Noop)
  
  //update pool detail response 
  object updatePoolDetail extends RequestVar[() => JsCmd](() => Noop)

  object poolsWithRoles extends RequestVar[() => JsCmd](() => Noop)

  object poolId extends RequestVar[Long](0)


  /*
  * Function for adding pools
  *
  */
  def addPool(in: NodeSeq): NodeSeq = {

    // redisplay my pools and roles
    val redisplayPoolsAndRoles = poolsWithRoles.is
  
    val theInput = "new_pool"
    val newPoolDescription = "new_pool_description";
    val user = User.currentUser
    var newPoolName = "";

      
    //def addNewPool(name: String) = {
    def addNewPool(poolDescription: String) = {

      /*
      name.trim match {
        case x if x.length < 3 => DisplayMessage("messages", <b>{S.?("base_pool_error_name_short")}</b>,  3 seconds, 3 seconds)
        case x => {
      */
      (newPoolName.trim, poolDescription.trim) match {
        case (x, y) if x.length < 3 => DisplayMessage("messages", <b>{S.?("base_pool_error_name_short")}</b>,  3 seconds, 3 seconds)
        case (x, y) => {
          import org.apache.esme.model.AccessPool
          //val pool = AccessPool.create.realm(AccessPool.Native).setName(name)
          val pool = AccessPool.create.realm(AccessPool.Native).setUpAccessPool(x, y)
          pool match {
            //case Failure(_,_,_) => DisplayMessage("messages", <b>{S.?("base_pool_msg_duplicate_name_pool",name)}</b>,  3 seconds, 2 seconds)
            case Failure(_,_,_) => DisplayMessage("messages", <b>{S.?("base_pool_msg_duplicate_name_pool",x)}</b>,  3 seconds, 2 seconds)
            case Full(p: AccessPool) => val privilegeSaved =
              Privilege.create.pool(p.saveMe).user(user).permission(Permission.Admin).save
              if(privilegeSaved && user.isDefined) {
                import org.apache.esme.model.{Privilege, User}
                Distributor ! Distributor.AllowUserInPool(user.get.id.is, p.id.is)
                //logger.info("ACCESS: " + S.?("base_pool_msg_new_pool",name))
                logger.info("ACCESS: " + S.?("base_pool_msg_new_pool",x))
                val selectPools = ("0", S.?("base_pool_msg_choose_pool")) ::
                (User.currentUser match {
                  case Full(u)=> Privilege.findViewablePools(u.id).map(
                    p => (p.toString, AccessPool.find(p).get.getName)).toList
                  case _ => Nil
                }).sortWith(_._2 < _._2)
                SetValById(theInput, "")  &
                ReplaceOptions("edit_pool", selectPools, Full(p.id.is.toString))  &
                FireOnchangeById("edit_pool") &
                redisplayPoolsAndRoles() &
                //DisplayMessage("messages", <b>{S.?("base_pool_msg_new_pool",name)}</b>,  3 seconds, 2 seconds)
                DisplayMessage("messages", <b>{S.?("base_pool_msg_new_pool",x)}</b>,  3 seconds, 2 seconds)
              } else
                DisplayMessage("messages", <b>{S.?("base_pool_msg_no_permission")}</b>,  3 seconds, 2 seconds)
            case _ => S.error(S.?("base_error_general"))
          }
        }
      }

    }

    case class FireOnchangeById(domElemId: String) extends JsCmd {
      def toJsCmd =
        """document.getElementById(""" + domElemId.encJs + """).onchange();"""
    }

    bind("add", in,
         //"poolName" -%> text("", addNewPool, "id" -> theInput),
         "poolName" -%> text("", newPoolName = _ , "id" -> theInput),
         "poolDescription" -%> textarea("", addNewPool, "id" -> newPoolDescription, "cols" -> "33", "rows" -> "2"))

  }

  var lastSelPool = "";

  /*
  * Function for editing pools
  *
  */
  def editPool(in: NodeSeq): NodeSeq = {
    import org.apache.esme.model.{AccessPool, User}
    val redisplayPool = updatePool.is

    // redisplay pool detail
    val redisplayPoolDetail = updatePoolDetail.is

    val redisplayPoolsAndRoles = poolsWithRoles.is

    // redisplay pool users and pool detail
    def redisplay(): JsCmd = {
      redisplayPoolDetail() & redisplayPool() & redisplayPoolsAndRoles()
    }

    var pool = ""
    var username = ""
    val editPoolName = "edit_pool"
    val editUsername = "edit_username"
    val editPermission = "edit_permission"
    val adminUser = User.currentUser

    val adminPools = ("0", S.?("base_pool_msg_choose_pool")) ::
    (adminUser match {
      case Full(u)=> Privilege.findViewablePools(u.id).map(
        p => (p.toString, AccessPool.find(p).get.getName)).toList
      case _ => Nil
    })

    val permissions = Permission.values.map(perm => (perm.id.toString, perm.toString)).toSeq


      /*
       * Function for adding a user to a pool
       *
       */
    def addPoolUser(permission: String): JsCmd = {
      pool = lastSelPool;
      val r: Box[Boolean] =
      for (admin <- adminUser;
           p <- AccessPool.find(pool) ?~ S.?("base_pool_err_pool_not_found"); //DisplayMessage("messages", <b>{S.?("base_pool_err_pool_not_found")}</b>,  3 seconds, 2 seconds);
           user <- User.findFromWeb(username) ?~ S.?("base_pool_err_user_not_found") //DisplayMessage("messages", <b>{S.?("base_pool_err_user_not_found")}</b>,  3 seconds, 2 seconds)
      ) yield if(Privilege.hasPermission(admin.id.is, p.id.is, Permission.Admin)) {
        val result = try {
          import org.apache.esme.model.Permission
          logger.info("ACCESS: " + S.?("base_pool_msg_new_user",user.id.is, p.id.is, permission))
          Privilege.create.user(user).pool(p).permission(Permission(permission.toInt)).save

        } catch {
          case _: Exception => false
        }
        if (result) {
        	Distributor ! Distributor.AllowUserInPool(user.id.is, p.id.is)   	
        	DisplayMessage("messages", <b>{S.?("base_pool_msg_permission_set")}</b>,  3 seconds, 2 seconds)
       }
        result
      } else false // "User has no permission to administer pool"
       /*
      r match {
        case Failure(m,_,_) => S.error(m)
        case Full(true) => S.notice(S.?("base_pool_msg_permission_set"))
        case _ => S.error(S.?("base_error_general"))
      }
      */

      poolId.set(pool.toLong)

      ( r match {
        case Failure(m,_,_) => DisplayMessage("messages", <b>{m}</b>,  3 seconds, 2 seconds)//S.error(m)
        case Full(true) => DisplayMessage("messages", <b>{S.?("base_pool_msg_permission_set")}</b>,  3 seconds, 2 seconds)//S.notice(S.?("base_pool_msg_permission_set"))
        case _ => DisplayMessage("messages", <b>{S.?("base_error_general")}</b>,  3 seconds, 2 seconds)//S.error(S.?("base_error_general"))
      } ) & 
      //we needn't redisplay pool detail when add a new user
      redisplayPool() & SetValById(editUsername, "") &
      redisplayPoolsAndRoles()
    }

    /*
    bind("edit", in,
         "pool" -%> ajaxSelect(adminPools, Empty, p => {pool = p;
                                                       poolId.set(p.toLong);
                                                       redisplay() //redisplay pooluser and pool detail
                                                       },
                                                 "id" -> editPoolName),
         "username" -%> text(username, username = _, "id" -> editUsername),
         "permission" -%> select(permissions, Empty, addPoolUser, "id" -> editPermission)
    )
    */

    /*
    bind("edit", in,
         "pool" -%> org.apache.esme.liftwebext.SHtml.ajaxUntrustedSelect(adminPools, Empty, (p:String) => {lastSelPool = p;  pool = p;
                                                       poolId.set(p.toLong);
                                                       redisplay() //redisplay pooluser and pool detail
                                                       },
                                                 "id" -> editPoolName),
         "username" -%> text(username, username = _, "id" -> editUsername),
         "permission" -%> select(permissions, Empty, addPoolUser, "id" -> editPermission)
    )
    */

    bind("edit", in,
         "pool" -%> org.apache.esme.liftwebext.SHtml.ajaxUntrustedSortedSelect(adminPools,
                                                       true,
                                                       Empty, (p:String) => {lastSelPool = p;  pool = p;
                                                       poolId.set(p.toLong);
                                                       redisplay() //redisplay pooluser and pool detail
                                                       },
                                                 "id" -> editPoolName),
         "username" -%> AutoComplete("", (current : String,limit : Int) =>
          User.findAll(Like(User.nickname, (current + "%"))).map(_.nickname.is),
          username = _ : String,
          List(("selectFirst", "false"), ("minChars", "1")),
          "name" -> editUsername),
         "permission" -%> select(permissions, Empty, addPoolUser, "id" -> editPermission)
    )
  }

  def myPoolsWithRoles(in: NodeSeq): NodeSeq = {

    // get the span name to update
    val spanName = S.attr("the_id") openOr "pool_membership_and_roles"

    def doRender(): NodeSeq = {

      val user = User.currentUser

      val userPools =
        (user match {
          case Full(u)=> Privilege.findViewablePools(u.id).map(
            p => (p, AccessPool.find(p).get.getName))
          case _ => Nil
        })

      val userPerms = userPools.map((x: (Long, String)) => Privilege.getPermissionString(user.open_!.id, x._1));
      val poolsAndRoles = userPools.map(_._2).zip(userPerms)

      bind("myPool", in,
          "pool" ->
             (in1 =>
                poolsAndRoles.flatMap((x: (String, String)) =>
                                            bind("pool", in1,
                                              "poolName" -> x._1,
                                              "role" -> x._2
               ))))
    }

    def updateSpan(): JsCmd = SetHtml(spanName, doRender())
    poolsWithRoles.set(updateSpan)
    doRender
  }

  def displayPoolDetail(in: NodeSeq): NodeSeq = {
    import org.apache.esme.model.AccessPool
    // get the span name to update
    val spanName = S.attr("the_pool_id") openOr "PoolDetailSpan"

    //XXX display date, should we have a common dateFormat?
    val dateFormat = new SimpleDateFormat("yyyy/MM/dd")
    def getDateHtml(date: Date) : Text = date match {
     case null => Text(S.?("base_pool_ui_empty_date"))
     case d => Text(dateFormat.format(d))
   }

    def displayUserName(uid: Long): NodeSeq = {
      User.find(uid) match {
        case Full(user) => <span>{user.nickname}</span>
        case _ => NodeSeq.Empty
      }
    }

    def doRender(): NodeSeq = 
       AccessPool.find(By(AccessPool.id, poolId.is)) match {
        case Full(ap) => {         
          bind(
            "pool", in,
            "name" -> (if ( ap.description == "" ) ap.getName else ap.getName + " - " + ap.description),
            "creator" -> displayUserName( ap.creator ),
            "createdDate" -> getDateHtml(ap.createdDate),
            "modifier" -> displayUserName(ap.modifier),
            "lastModifyDate" -> getDateHtml(ap.lastModifyDate)) }
      case _ => NodeSeq.Empty
      }
    
    def updateSpan(): JsCmd = SetHtml(spanName, doRender())
    updatePoolDetail.set(updateSpan)
    doRender
  }
  
  def displayPoolUsers(in: NodeSeq): NodeSeq = {
    // get the span name to update
    val spanName = S.attr("the_id") openOr "PoolSpan"
    // get the current user
    val user = User.currentUser

      // Distributor ! Distributor.RefreshUser(userId)
    def doRender(): NodeSeq = {
    val accessPool = AccessPool.find(By(AccessPool.id, poolId.is))  
    Privilege.findAll(By(Privilege.pool, poolId.is), NotBy(Privilege.permission, Permission.Denied)) match {
      case Nil => NodeSeq.Empty
      case xs => {
        def userNamePrivilege(lst : NodeSeq) : NodeSeq = {
          xs.flatMap(i => bind("user", lst,
                               "name" -> User.find(i.user).map(
                                         _.nickname.is).getOrElse(""),
                               "privilege" -> i.permission.is.toString
                          ))
        }

        def renderEditButton(in : NodeSeq) : NodeSeq = if(Privilege.findAdminPools(user.open_!.id).contains(poolId.is)) in else NodeSeq.Empty

        bind("pool", in,
          "user" -> userNamePrivilege _,
          "action" -> renderEditButton _)
      }
    }
    }

    def updateSpan(): JsCmd = SetHtml(spanName, doRender())

    updatePool.set(updateSpan)
    doRender
 }
}
