package com.atlassian.confluence.extra.userlister;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Map;

import com.atlassian.confluence.extra.userlister.model.UserList;
import com.atlassian.confluence.renderer.radeox.macros.MacroUtils;
import com.atlassian.confluence.user.UserAccessor;
import com.atlassian.confluence.util.VelocityUtils;
import com.atlassian.renderer.RenderContext;
import com.atlassian.renderer.v2.RenderMode;
import com.atlassian.renderer.v2.macro.BaseMacro;
import com.atlassian.renderer.v2.macro.MacroException;
import org.apache.log4j.Category;

public class UserLister extends BaseMacro
{
    UserAccessor userAccessor;
    private Hashtable loggedInUsers = new Hashtable();

    private static Category logger = Category.getInstance(UserLister.class);

    public void setUserAccessor(UserAccessor userAccessor)
    {
        this.userAccessor = userAccessor;
    }

    public void userLoggedIn(String username, String sessionId)
    {
        loggedInUsers.put(sessionId, username);
    }

    public void userLoggedOut(String sessionId)
    {
        loggedInUsers.remove(sessionId);
    }

    public Map getLoggedInUsers()
    {
       return loggedInUsers;
    }

    public boolean isInline()
    {
        return false;
    }

    public boolean hasBody()
    {
        return false;
    }

    public RenderMode getBodyRenderMode()
    {
        return RenderMode.ALL;
    }

    public String execute(Map parameters, String body, RenderContext renderContext) throws MacroException
    {
        //1. parse parameters from macro
        String listNames  = (String) parameters.get("groups");
        String online = (String) parameters.get("online");

        String groups[] = parseGroups(listNames);
        boolean returnOnlineUsers = parseOnline(online);

        Collection loggedInUsernames = loggedInUsers.values();
        ArrayList groupList = new ArrayList();

        for (int i = 0; i < groups.length; i++)
        {
            if (groups[i] != null)
                groups[i] = groups[i].trim();

            UserList userList = new UserList(groups[i], userAccessor);

            if (!userList.build(online != null, loggedInUsernames, returnOnlineUsers))
            {
                return ("Could not find group(s) named: " + groups[i]);
            }

            if (!userList.getUsers().isEmpty())
                groupList.add(userList);
        }

        // now create a simple velocity context and render a template for the output
        Map contextMap = MacroUtils.defaultVelocityContext();
        contextMap.put("userlists", groupList);
        if (online != null)
            contextMap.put("online", new Boolean(returnOnlineUsers));

        try
        {
            return VelocityUtils.getRenderedTemplate("templates/extra/userlister/userlistermacro.vm", contextMap);
        }
        catch (Exception e)
        {
            logger.error("Error while trying to display UserList!", e);
            return("Error while trying to display UserList! The template used to construct the userlister could not be loaded from the filesystem. \n Please contact an administrator with the following stacktrace:  " + e);
        }
    }

    private boolean parseOnline(String online)
    {
        //check to see whether an online="true" parameter was passed through
        //it will default to false unless "true" in lower case appears

        if (online != null)
        {
            return new Boolean(online.toLowerCase()).booleanValue();
        }
        return false;
    }

    private String [] parseGroups(String listNames)
    {
        String [] groups;

        //is listNames a list of groups or just a single group?
        if (listNames != null)
        {
            groups = listNames.split(",");
        }
        else
        {
            groups = new String[]{null};
        }

        return groups;
    }
}
