package de.codescape.jira.plugins.scrumpoker.service;

import com.atlassian.activeobjects.external.ActiveObjects;
import com.atlassian.jira.issue.IssueManager;
import com.atlassian.plugin.spring.scanner.annotation.component.Scanned;
import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport;
import de.codescape.jira.plugins.scrumpoker.ao.ScrumPokerSession;
import de.codescape.jira.plugins.scrumpoker.ao.ScrumPokerVote;
import net.java.ao.DBParam;
import net.java.ao.Query;

import javax.inject.Inject;
import javax.inject.Named;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import static com.google.common.base.Preconditions.checkNotNull;

@Scanned
@Named
public class DefaultScrumPokerSessionService implements ScrumPokerSessionService {

    private static final int POKER_SESSION_TIMEOUT_HOURS = 12;

    @ComponentImport
    private final ActiveObjects activeObjects;

    @ComponentImport
    private final IssueManager issueManager;

    @Inject
    public DefaultScrumPokerSessionService(ActiveObjects activeObjects, IssueManager issueManager) {
        this.activeObjects = checkNotNull(activeObjects);
        this.issueManager = issueManager;
    }

    @Override
    public List<ScrumPokerSession> recent() {
        Date date = new Date(System.currentTimeMillis() - 3600 * 1000 * POKER_SESSION_TIMEOUT_HOURS);
        return Arrays.asList(activeObjects.find(ScrumPokerSession.class, Query.select()
            .where("CREATE_DATE > ?", date).order("CREATE_DATE DESC")));
    }

    @Override
    public ScrumPokerSession byIssueKey(String issueKey, String userKey) {
        ScrumPokerSession scrumPokerSession = activeObjects.get(ScrumPokerSession.class, issueKey);
        if (scrumPokerSession == null)
            scrumPokerSession = create(issueKey, userKey);
        return scrumPokerSession;
    }

    @Override
    public ScrumPokerSession addVote(String issueKey, String userKey, String vote) {
        ScrumPokerSession scrumPokerSession = byIssueKey(issueKey, userKey);
        scrumPokerSession.setVisible(false);
        scrumPokerSession.save();

        ScrumPokerVote[] scrumPokerVotes = activeObjects.find(ScrumPokerVote.class, Query.select()
            .where("SESSION_ID = ? and USER_KEY = ?", issueKey, userKey));
        ScrumPokerVote scrumPokerVote;
        if (scrumPokerVotes.length == 0) {
            scrumPokerVote = activeObjects.create(ScrumPokerVote.class);
            scrumPokerVote.setSession(scrumPokerSession);
            scrumPokerVote.setUserKey(userKey);
        } else {
            scrumPokerVote = scrumPokerVotes[0];
        }
        scrumPokerVote.setCreateDate(new Date());
        scrumPokerVote.setVote(vote);
        scrumPokerVote.save();
        return scrumPokerSession;
    }

    @Override
    public ScrumPokerSession reveal(String issueKey, String userKey) {
        ScrumPokerSession scrumPokerSession = byIssueKey(issueKey, userKey);
        scrumPokerSession.setVisible(true);
        scrumPokerSession.save();
        return scrumPokerSession;
    }

    @Override
    public ScrumPokerSession confirm(String issueKey, String userKey, Integer estimation) {
        ScrumPokerSession scrumPokerSession = byIssueKey(issueKey, userKey);
        scrumPokerSession.setConfirmedVote(estimation);
        scrumPokerSession.save();
        return scrumPokerSession;
    }

    @Override
    public ScrumPokerSession reset(String issueKey, String userKey) {
        ScrumPokerVote[] votes = activeObjects.find(ScrumPokerVote.class, Query.select()
            .where("SESSION_ID = ?", issueKey));
        Arrays.stream(votes).forEach(activeObjects::delete);
        activeObjects.delete(byIssueKey(issueKey, userKey));
        return byIssueKey(issueKey, userKey);
    }

    @Override
    public List<ScrumPokerSession> references(String userKey, Integer estimation) {
        return Arrays.asList(activeObjects.find(ScrumPokerSession.class, Query.select()
            .alias(ScrumPokerSession.class, "session")
            .alias(ScrumPokerVote.class, "vote")
            .join(ScrumPokerVote.class, "vote.SESSION_ID = session.ISSUE_KEY")
            .where("vote.USER_KEY = ? and session.CONFIRMED_VOTE = ?", userKey, estimation)
            .order("session.CREATE_DATE DESC")
            .limit(3)));
    }

    private ScrumPokerSession create(String issueKey, String userKey) {
        if (issueManager.getIssueObject(issueKey) == null) {
            throw new IllegalStateException("Unable to create session for issue with key " + issueKey + " because could not find this issue.");
        }
        ScrumPokerSession scrumPokerSession = activeObjects.create(ScrumPokerSession.class,
            new DBParam("ISSUE_KEY", issueKey));
        scrumPokerSession.setCreateDate(new Date());
        scrumPokerSession.setCreatorUserKey(userKey);
        scrumPokerSession.setVisible(false);
        scrumPokerSession.setConfirmedVote(null);
        scrumPokerSession.save();
        return scrumPokerSession;
    }

}

@@ -4553,16 +4553,32 @@
 issueKey
+%0A               
  + %22 bec

format code