package io.cattle.platform.agent.instance.dao.impl;

import static io.cattle.platform.core.model.tables.AgentTable.*;
import static io.cattle.platform.core.model.tables.CredentialTable.*;
import static io.cattle.platform.core.model.tables.InstanceLabelMapTable.*;
import static io.cattle.platform.core.model.tables.InstanceTable.*;
import static io.cattle.platform.core.model.tables.LabelTable.*;
import static io.cattle.platform.core.model.tables.InstanceHostMapTable.*;
import static io.cattle.platform.core.model.tables.HostTable.*;

import io.cattle.platform.agent.instance.dao.AgentInstanceDao;
import io.cattle.platform.core.constants.AgentConstants;
import io.cattle.platform.core.constants.CommonStatesConstants;
import io.cattle.platform.core.constants.HealthcheckConstants;
import io.cattle.platform.core.constants.InstanceConstants;
import io.cattle.platform.core.dao.GenericResourceDao;
import io.cattle.platform.core.model.Agent;
import io.cattle.platform.core.model.Credential;
import io.cattle.platform.core.model.Instance;
import io.cattle.platform.db.jooq.dao.impl.AbstractJooqDao;
import io.cattle.platform.object.ObjectManager;
import io.cattle.platform.object.util.DataAccessor;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.inject.Inject;

import org.jooq.Record2;
import org.jooq.RecordHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class AgentInstanceDaoImpl extends AbstractJooqDao implements AgentInstanceDao {

    @Inject
    private static final Logger log = LoggerFactory.getLogger(AgentInstanceDaoImpl.class);

    GenericResourceDao resourceDao;
    
    @Inject
    ObjectManager objectManager;

    @Override
    public Agent getAgentByUri(String uri) {
        return create()
                .selectFrom(AGENT)
                .where(AGENT.URI.eq(uri)
                        .and(AGENT.REMOVED.isNull()))
                .fetchAny();
    }

    @Override
    public Instance getInstanceByAgent(Long agentId) {
        if (agentId == null) {
            return null;
        }

        return create()
                .selectFrom(INSTANCE)
                .where(INSTANCE.AGENT_ID.eq(agentId)
                        .and(INSTANCE.REMOVED.isNull())
                        .and(INSTANCE.STATE.notIn(InstanceConstants.STATE_ERROR, InstanceConstants.STATE_ERRORING,
                                CommonStatesConstants.REMOVING)))
                .fetchAny();
    }

    @Override
    public boolean areAllCredentialsActive(Agent agent) {
        List<Long> authedRoleAccountIds = DataAccessor.fieldLongList(agent, AgentConstants.FIELD_AUTHORIZED_ROLE_ACCOUNTS);

        if (agent.getAccountId() == null) {
            return false;
        }

        Set<Long> accountIds = new HashSet<>();
        accountIds.add(agent.getAccountId());

        for (Long aId : authedRoleAccountIds) {
            accountIds.add(aId);
        }

        List<? extends Credential> creds = create()
                .selectFrom(CREDENTIAL)
                .where(CREDENTIAL.STATE.eq(CommonStatesConstants.ACTIVE)
                        .and(CREDENTIAL.ACCOUNT_ID.in(accountIds)))
                .fetch();

        Set<Long> credAccountIds = new HashSet<>();
        for (Credential cred : creds) {
            credAccountIds.add(cred.getAccountId());
        }

        return accountIds.equals(credAccountIds);
    }

    @Override
    public List<Long> getAgentProvider(String providedServiceLabel, long accountId) {
        final Map<Long, Integer> result = new HashMap<>();
        create().select(INSTANCE.AGENT_ID, LABEL.VALUE)
                .from(INSTANCE)
                .join(INSTANCE_LABEL_MAP)
                    .on(INSTANCE_LABEL_MAP.INSTANCE_ID.eq(INSTANCE.ID))
                .join(LABEL)
                    .on(LABEL.ID.eq(INSTANCE_LABEL_MAP.LABEL_ID).and(LABEL.KEY.eq(providedServiceLabel)))
                .join(INSTANCE_HOST_MAP)
                    .on(INSTANCE.ID.eq(INSTANCE_HOST_MAP.INSTANCE_ID))
                .join(HOST)
                    .on(INSTANCE_HOST_MAP.HOST_ID.eq(HOST.ID))
                .join(AGENT)
                    .on(AGENT.ID.eq(HOST.AGENT_ID))
                .where(INSTANCE.ACCOUNT_ID.eq(accountId)
                    .and(INSTANCE.AGENT_ID.isNotNull())
                        .and(INSTANCE.STATE.eq(InstanceConstants.STATE_RUNNING))
                        .and(INSTANCE.HEALTH_STATE.in(HealthcheckConstants.HEALTH_STATE_HEALTHY,
                                HealthcheckConstants.HEALTH_STATE_UPDATING_HEALTHY)))
                        .and(AGENT.STATE.eq(CommonStatesConstants.ACTIVE))
                .orderBy(INSTANCE.AGENT_ID.asc())
        .fetchInto(new RecordHandler<Record2<Long, String>>() {
            @Override
            public void next(Record2<Long, String> record) {
                Long agentId = record.getValue(INSTANCE.AGENT_ID);
                String p = record.getValue(LABEL.VALUE);
                Integer pVal = 1;
                try {
                    pVal = Integer.valueOf(p);
                } catch (Exception e) {
                    log.warn("Priority value not found for agent {}. Set it as default", agentId);
                }
                result.put(agentId, pVal);
            }
        });
        
        List<Long> returnAgentIds = new ArrayList<>(result.keySet());
        
        Collections.sort(returnAgentIds, new Comparator<Long>() {
            @Override
            public int compare(Long id1, Long id2) {
                return result.get(id1).compareTo(result.get(id2));
            }
        });
        
        return returnAgentIds;
        
    }

    @Override
    public List<Long> getAgentProviderIgnoreHealth(String providedServiceLabel, long accountId) {
        return Arrays.asList(create().select(INSTANCE.AGENT_ID)
                .from(INSTANCE)
                .join(INSTANCE_LABEL_MAP)
                    .on(INSTANCE_LABEL_MAP.INSTANCE_ID.eq(INSTANCE.ID))
                .join(LABEL)
                    .on(LABEL.ID.eq(INSTANCE_LABEL_MAP.LABEL_ID).and(LABEL.KEY.eq(providedServiceLabel)))
                .where(INSTANCE.ACCOUNT_ID.eq(accountId)
                        .and(INSTANCE.AGENT_ID.isNotNull())
                        .and(INSTANCE.SYSTEM.isTrue())
                        .and(INSTANCE.STATE.in(InstanceConstants.STATE_RUNNING, InstanceConstants.STATE_STARTING)))
                .orderBy(INSTANCE.AGENT_ID.asc())
                .fetch().intoArray(INSTANCE.AGENT_ID));
    }
}
@@ -5283,12 +5283,13 @@
 log.
-warn
+debug
 (%22Pr

disable logs