module UserSystem

  protected

  # authenticate_user filter. add
  #
  #   before_filter :authenticate_user
  #
  def authenticate_user
    if authenticated_user = authenticated_user?
      self.current_user = authenticated_user
      return true
    end
    session[:user_id]     = nil
    Thread.current[:user] = nil
    store_detour(params)
    access_denied
    return false
  end

  # overwrite if you want to have special behavior in case the user is not authorized
  # to access the current operation. 
  # the default action is to redirect to the login screen
  # example use :
  # a popup window might just close itself for instance
  def access_denied
    redirect_to :controller => "/user", :action => "login"
  end

  def redirect_back_or_default(default)
    if session[:return_to].nil?
      redirect_to default
    else
      redirect_to_url session[:return_to]
      session[:return_to] = nil
    end
  end

  def authenticated_user?
    if session[:user_id]
      current_user = User.find_by_id(session[:user_id])
      return current_user if current_user
      session[:user_id] = nil
    end

    if cookie = cookies[:autologin]
      cookie_value =
          case cookie
          when String
            cookie
          when Hash
            cookie[:value].first
          when CGI::Cookie
            cookie.first[:value].first
          else
            raise "Unknown cookie class: #{cookie.class}"
          end
      token_cookie = cookies[:token]
      token_value        = token_cookie &&
          case token_cookie
          when String
            token_cookie
          when Hash
            token_cookie[:value].first
          when CGI::Cookie
            token_cookie.first[:value].first
          else
            raise "Unknown cookie class: #{cookie.class}"
          end
      begin
        cookie_user = User.authenticate_by_token(Integer(cookie_value), token_value)
      rescue ArgumentError => e
        logger.warn e
      end
      cookie_user ||= User.authenticate(cookie_value, '')

      return cookie_user if cookie_user
    end

    # If not, is the user being authenticated by a token (created by signup/forgot password actions)?
    return false if not params['user']
    id  = params['user']['id']
    key = params['key']
    if id and key
      return current_user if current_user = User.authenticate_by_token(id, key)
    end

    # Everything failed
    return false
  end

  def current_user
    Thread.current[:user]
  end

  def current_user= user
    session[:user_id] = user && user.id if self.respond_to?(:session)
    Thread.current[:user] = user
  end

end