package org.iri_research.renkan.coweb.event;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.inject.Named;

import org.coweb.CowebException;
import org.iri_research.renkan.models.RenkanSessionModeratorState;
import org.iri_research.renkan.models.RosterUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Named
public class RosterSyncEventManager implements
        ISyncEventManager<RosterUser, String> {

    private final Logger logger = LoggerFactory
            .getLogger(RosterSyncEventManager.class);

    @Override
    public void insert(String clientId, Map<String, Object> data) {
        logger.debug("RosterUserSyncEventManager.insert " + data.toString());

        @SuppressWarnings("unchecked")
        Map<String, Object> values = (Map<String, Object>) data.get("value");
        String projectId = (String) values.get("_project_id");

        List<RosterUser> usersList = null;

        if (RenkanSessionModeratorState.INSTANCE.getProjectsUsersList()
                .containsKey(projectId)) {
            usersList = RenkanSessionModeratorState.INSTANCE
                    .getProjectsUsersList().get(projectId);
        }
        if (usersList == null) {
            usersList = new ArrayList<RosterUser>();
            RenkanSessionModeratorState.INSTANCE.getProjectsUsersList().put(
                    projectId, usersList);
        }

        String id = (String) values.get("id");

        RosterUser user = null;

        for (RosterUser rosterUser : usersList) {
            if (rosterUser.getId().equals(id)) {
                user = rosterUser;
                break;
            }
        }
        if (user != null) {
            this.update(clientId, data);
            return;
        }

        String title = (String) values.get("title");
        String description = (String) values.get("description");
        String uri = (String) values.get("uri");
        String color = (String) values.get("color");
        Long site_id = (Long) values.get("site_id");

        user = new RosterUser(id, title, description, uri, color, projectId,
                site_id, clientId);

        Integer position = (Integer) data.get("position");
        if (position == null) {
            position = new Integer(0);
        }

        usersList.add(position.intValue(), user);

        logger.debug("RosterUserSyncEventManager.insert in  "
                + projectId
                + " : "
                + RenkanSessionModeratorState.INSTANCE
                        .getProjectsActivationMap().toString());

    }

    @Override
    public void nullOperation(String clientId, Map<String, Object> data) {
        // do nothing
        return;
    }

    @Override
    public void update(String clientId, Map<String, Object> data) {
        logger.debug("RosterUserSyncEventManager.update " + data.toString());

        @SuppressWarnings("unchecked")
        Map<String, Object> values = (Map<String, Object>) data.get("value");
        String projectId = (String) values.get("_project_id");

        List<RosterUser> usersList = null;

        if (RenkanSessionModeratorState.INSTANCE.getProjectsUsersList()
                .containsKey(projectId)) {
            usersList = RenkanSessionModeratorState.INSTANCE
                    .getProjectsUsersList().get(projectId);
        }

        if (usersList == null) {
            logger.debug("RosterUserSyncEventManager.update : null user list");
            return;
        }

        String id = (String) values.get("id");

        RosterUser user = null;

        for (RosterUser rosterUser : usersList) {
            if (rosterUser.getId().equals(id)) {
                user = rosterUser;
                break;
            }
        }

        if (user == null) {
            logger.debug("RosterUserSyncEventManager.update : user not found in list");
            return;
        }

        String title = (String) values.get("title");
        String description = (String) values.get("description");
        String uri = (String) values.get("uri");
        String color = (String) values.get("color");

        if (title != null) {
            user.setTitle(title);
        }
        if (description != null) {
            user.setDescription(description);
        }
        if (uri != null) {
            user.setUri(uri);
        }
        if (color != null) {
            user.setColor(color);
        }

        return;

    }

    @Override
    public void delete(String clientId, Map<String, Object> data) {
        logger.debug("RosterUserSyncEventManager.delete " + data.toString());

        @SuppressWarnings("unchecked")
        Map<String, Object> values = (Map<String, Object>) data.get("value");
        String projectId = (String) values.get("_project_id");

        List<RosterUser> usersList = null;

        if (RenkanSessionModeratorState.INSTANCE.getProjectsUsersList()
                .containsKey(projectId)) {
            usersList = RenkanSessionModeratorState.INSTANCE
                    .getProjectsUsersList().get(projectId);
        }

        if (usersList == null) {
            logger.debug("RosterUserSyncEventManager.delete : null user list");
            return;
        }

        Integer position = (Integer) data.get("position");

        if (position == null || position < 0) {
            throw new CowebException("object delete: bad delete position",
                    String.format("Bad position %s not found",
                            position == null ? "null" : position.toString()));
        }
        int index = position.intValue();

        usersList.remove(index);

        if (usersList.isEmpty()) {
            RenkanSessionModeratorState.INSTANCE.getProjectsUsersList().remove(
                    projectId);
        }

        return;

    }

    @Override
    public void dispatchEvent(String clientId, Map<String, Object> data) {

        String eventType = (String) data.get("type");

        if ("null".equalsIgnoreCase(eventType)) {
            this.nullOperation(clientId, data);
        } else if ("update".equalsIgnoreCase(eventType)) {
            this.update(clientId, data);
        } else if ("insert".equalsIgnoreCase(eventType)) {
            this.insert(clientId, data);
        } else if ("delete".equalsIgnoreCase(eventType)) {
            this.delete(clientId, data);
        } else {
            logger.warn(String.format("dispatchEvent : eventType unknown %s",
                    eventType));
        }
    }

}
