/*
 * Copyright 2018 Scytl Secure Electronic Voting SA
 *
 * All rights reserved
 *
 * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
 */
package com.scytl.products.ov.kt.services.infrastructure.persistence.impl;

import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.NoResultException;
import javax.persistence.TypedQuery;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.scytl.products.ov.commons.beans.exceptions.BallotBoxTranslationRepositoryException;
import com.scytl.products.ov.commons.beans.exceptions.DuplicateEntryException;
import com.scytl.products.ov.commons.beans.exceptions.EntryPersistenceException;
import com.scytl.products.ov.commons.beans.exceptions.ResourceNotFoundException;
import com.scytl.products.ov.commons.infrastructure.persistence.BaseRepositoryImpl;
import com.scytl.products.ov.kt.domain.model.ballotbox.BallotBoxTranslation;
import com.scytl.products.ov.kt.services.BallotBoxTranslationService;
import com.scytl.products.ov.kt.services.infrastructure.persistence.BallotBoxTranslationRepository;

/**
 * Implementation of the repository with jpa
 */
@Stateless
public class BallotBoxTranslationRepositoryImpl extends BaseRepositoryImpl<BallotBoxTranslation, Integer>
    implements BallotBoxTranslationRepository {

    private static final Logger LOG = LoggerFactory.getLogger(BallotBoxTranslationService.class);

	private static final String PARAMETER_TENANT_ID = "tenantId";

    private static final String PARAMETER_ALIAS = "alias";

    private static final String PARAMETER_ELECTION_EVENT_ID = "electionEventId";

    private static final String PARAMETER_BALLOT_BOX_ID = "ballotBoxId";

    /**
     * @see BallotBoxTranslationRepository#findByAlias(String,
     *      String)
     */
    @Override
    public BallotBoxTranslation findByAlias(String tenantId, String electionEventId, String alias) throws ResourceNotFoundException {
        TypedQuery<BallotBoxTranslation> query = entityManager.createQuery(
            "SELECT e FROM BallotBoxTranslation e WHERE e.tenantId = :tenantId " +
                "AND e.electionEventId = :electionEventId AND e.alias = :alias", BallotBoxTranslation.class);
        query.setParameter(PARAMETER_TENANT_ID, tenantId);
        query.setParameter(PARAMETER_ELECTION_EVENT_ID, electionEventId);
        query.setParameter(PARAMETER_ALIAS, alias);
        query.setMaxResults(1); //avoid exception for cases where we have different alias for the same
        try {
            return query.getSingleResult();
        } catch (NoResultException e) {
            throw new ResourceNotFoundException("Ballot Box translation not found", e);
        }
    }

    /**
     * @throws BallotBoxTranslationRepositoryException 
     * @see BallotBoxTranslationRepository#save(java.io.InputStream)
     */
    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public void saveOrUpdate(BallotBoxTranslation t) throws BallotBoxTranslationRepositoryException {
        BallotBoxTranslation boxTranslation;
        //check if alias already exists. if yes, update, if no, insert.
        try {
            boxTranslation = findByBallotBoxId(t.getTenantId(), t.getElectionEventId(), t.getBallotBoxId());
            boxTranslation.setAlias(t.getAlias());
            update(boxTranslation);
        } catch (ResourceNotFoundException e) {
            try {
                //does not exist. try to save
                save(t);
            } catch (DuplicateEntryException deE) {
                //should not happen...
				LOG.error("Duplicate entry found trying to save or update BallotBoxTranslation.", deE);
				throw new BallotBoxTranslationRepositoryException(String.format(
						"Duplicate entry for translation [tenantId=%s, electionEventId=%s, ballotBoxId=%s]",
						t.getTenantId(), t.getElectionEventId(), t.getBallotBoxId()), e);
            }
		} catch (EntryPersistenceException epE) {
			throw new BallotBoxTranslationRepositoryException(String.format(
					"Failed to save/update translation [tenantId=%s, electionEventId=%s, "
					+ "ballotBoxId=%s, alias=%s]",
					t.getTenantId(), t.getElectionEventId(), t.getBallotBoxId(), t.getAlias()), epE);
        }
    }

    @Override
    public BallotBoxTranslation findByBallotBoxId(final String tenantId, final String electionEventId,
                                                  final String ballotBoxId) throws ResourceNotFoundException {
        TypedQuery<BallotBoxTranslation> query = entityManager.createQuery(
            "SELECT e FROM BallotBoxTranslation e WHERE e.tenantId = :tenantId " +
                "AND e.electionEventId = :electionEventId AND e.ballotBoxId = :ballotBoxId", BallotBoxTranslation.class);
        query.setParameter(PARAMETER_TENANT_ID, tenantId);
        query.setParameter(PARAMETER_ELECTION_EVENT_ID, electionEventId);
        query.setParameter(PARAMETER_BALLOT_BOX_ID, ballotBoxId);
        try {
            return query.getSingleResult();
        } catch (NoResultException e) {
            throw new ResourceNotFoundException("Ballot Box translation not found", e);
        }
    }
}
