package com.bocloud.ims.repository.resource.hmc;

import com.bocloud.ims.entity.common.MapBuilder;
import com.bocloud.ims.entity.resource.hmc.HmdServerHea;
import com.bocloud.ims.entity.resource.hmc.HmdServerHeaLogicalPort;
import com.bocloud.ims.entity.resource.hmc.HmdServerHeaPhysicalPort;
import org.springframework.beans.factory.annotation.Lookup;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;

@Repository
public abstract class HmdServerHeaRepository extends HmdGenericDao<HmdServerHea> {

    @Lookup protected abstract HmdServerRepository serverRepository();
    @Lookup protected abstract HmdServerHeaLogicalPortRepository serverHeaLogicalPortRepository();
    @Lookup protected abstract HmdServerHeaPhysicalPortRepository serverHeaPhysicalPortRepository();

    public HmdServerHeaRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate npJdbcTemplate) {
        super(jdbcTemplate, npJdbcTemplate);
    }

    @Override
    public void extra(HmdServerHea hea) {
        Optional.of(hea).map(HmdServerHea::getId).map(this.serverHeaLogicalPortRepository()::listByServerId).ifPresent(hea::setLogicalPorts);
        Optional.of(hea).map(HmdServerHea::getId).map(this.serverHeaPhysicalPortRepository()::listByServerId).ifPresent(hea::setPhysicalPorts);
        Optional.of(hea).map(HmdServerHea::getServerId).map(this.serverRepository()::getById).ifPresent(hea::setServer);
    }

    public List<HmdServerHea> listByServerId(long serverId) {
        return this.search(Collections.singletonMap("a.server_id", serverId));
    }

    public HmdServerHea getById(long id) {
        return this.search(Collections.singletonMap("a.id", id)).stream().findFirst().orElse(null);
    }

    public HmdServerHea getByUuid(String uuid) {
        return this.search(Collections.singletonMap("a.uuid", uuid)).stream().findFirst().orElse(null);
    }

    public HmdServerHea getByAdapterId(long serverId, int adapterId) {
        Map<String, Object> map = MapBuilder.init().put("a.server_id", serverId).put("a.adapter_id", adapterId).get();
        return this.search(map).stream().findFirst().orElse(null);
    }

    @Override
    public void clear(long id) {
        this.serverHeaLogicalPortRepository().listByServerId(id).stream().map(HmdServerHeaLogicalPort::getId).forEach(this.serverHeaLogicalPortRepository()::clear);
        this.serverHeaPhysicalPortRepository().listByServerId(id).stream().map(HmdServerHeaPhysicalPort::getId).forEach(this.serverHeaPhysicalPortRepository()::clear);

        this.delete(id);
    }

    @Override
    public void syncInstance(HmdServerHea newT, HmdServerHea oldT, long userId) {
        super.syncInstance(newT, oldT, userId);
        Optional.of(newT).map(HmdServerHea::getLogicalPorts).ifPresent(newPorts -> {
            newPorts.forEach(port -> {
                port.setHeaId(newT.getId());
                port.setHea(newT);
            });
            List<HmdServerHeaLogicalPort> oldPorts = this.serverHeaLogicalPortRepository().listByServerId(newT.getId());
            this.serverHeaLogicalPortRepository().syncList(newPorts, oldPorts, userId);
        });
        Optional.of(newT).map(HmdServerHea::getPhysicalPorts).ifPresent(newPorts -> {
            newPorts.forEach(port -> {
                port.setHeaId(newT.getId());
                port.setHea(newT);
            });
            List<HmdServerHeaPhysicalPort> oldPorts = this.serverHeaPhysicalPortRepository().listByServerId(newT.getId());
            this.serverHeaPhysicalPortRepository().syncList(newPorts, oldPorts, userId);
        });
    }
}
