package ru.yandex.qe.dispenser.application.startup;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

import com.google.common.base.Stopwatch;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.dao.DuplicateKeyException;

import ru.yandex.qe.dispenser.domain.dao.dispenser_admins.DispenserAdminsDao;
import ru.yandex.qe.dispenser.domain.dao.entity.spec.EntitySpecDao;
import ru.yandex.qe.dispenser.domain.dao.group.GroupDao;
import ru.yandex.qe.dispenser.domain.dao.person.PersonDao;
import ru.yandex.qe.dispenser.domain.dao.person.PersonGroupMembershipDao;
import ru.yandex.qe.dispenser.domain.dao.project.ProjectDao;
import ru.yandex.qe.dispenser.domain.dao.project.role.ProjectRoleDao;
import ru.yandex.qe.dispenser.domain.dao.quota.spec.QuotaSpecDao;
import ru.yandex.qe.dispenser.domain.dao.resource.ResourceDao;
import ru.yandex.qe.dispenser.domain.dao.service.ServiceDao;

public abstract class InitialState implements ApplicationListener<ContextRefreshedEvent> {
    private static final Logger LOG = LoggerFactory.getLogger(InitialState.class);

    private static final AtomicBoolean CONFIGURED = new AtomicBoolean();

    @Autowired
    protected DispenserAdminsDao dispenserAdminsDao;

    @Autowired
    protected PersonDao personDao;

    @Autowired
    protected GroupDao groupDao;

    @Autowired
    protected ProjectDao projectDao;

    @Autowired
    protected ServiceDao serviceDao;

    @Autowired
    protected ResourceDao resourceDao;

    @Autowired
    protected QuotaSpecDao quotaSpecDao;

    @Autowired
    protected EntitySpecDao entitySpecDao;

    @Autowired
    protected PersonGroupMembershipDao personGroupMembershipDao;

    @Autowired
    protected ProjectRoleDao projectRoleDao;

    @Override
    public void onApplicationEvent(@NotNull final ContextRefreshedEvent cre) {
        if (CONFIGURED.compareAndSet(false, true)) {
            try {
                configureWithLogging();
            } catch (DuplicateKeyException e) {
                LOG.warn("May be, " + getClass().getSimpleName() + " already applied", e);
            }
        }
    }

    public void configureWithLogging() {
        LOG.debug("{} configuration started", getClass().getSimpleName());
        final Stopwatch stopwatch = Stopwatch.createStarted();
        configure();
        LOG.debug("{} configuration finished in {} ms", getClass().getSimpleName(), stopwatch.elapsed(TimeUnit.MILLISECONDS));
    }

    public abstract void configure() throws DuplicateKeyException;
}
