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

import com.bocloud.ims.entity.common.MapBuilder;
import com.bocloud.ims.entity.resource.hmc.HmdPartition;
import com.bocloud.ims.entity.resource.hmc.HmdViosVirtualCd;
import com.bocloud.ims.entity.resource.hmc.HmdViosVolumeGroup;
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 HmdViosVirtualCdRepository extends HmdGenericDao<HmdViosVirtualCd> {

    @Lookup protected abstract HmdPartitionRepository partitionRepository();
    @Lookup protected abstract HmdViosVolumeGroupRepository viosVolumeGroupRepository();

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

    @Override
    public void extra(HmdViosVirtualCd cd) {
        Optional.of(cd).map(HmdViosVirtualCd::getViosId).map(this.partitionRepository()::getById).ifPresent(cd::setVios);
        Optional.of(cd).map(HmdViosVirtualCd::getAssignPartitionId).map(this.partitionRepository()::getById).ifPresent(cd::setAssignPartition);
        Optional.of(cd).map(HmdViosVirtualCd::getVolumeGroupId).map(this.viosVolumeGroupRepository()::getById).ifPresent(cd::setVolumeGroup);
    }

    public List<HmdViosVirtualCd> listByViosId(long viosId) {
        return this.search(Collections.singletonMap("a.vios_id", viosId));
    }

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

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

    public HmdViosVirtualCd getByName(long viosId, String diskName) {
        Map<String, Object> map = MapBuilder.init()
            .put("a.vios_id", viosId)
            .put("a.name", diskName)
            .get();
        return this.search(map).stream().findFirst().orElse(null);
    }

    public List<HmdViosVirtualCd> listByViosAdapterId(long viosId, Integer viosAdapterId) {
        Map<String, Object> map = MapBuilder.init()
            .put("a.vios_id", viosId)
            .put("a.vios_slot_id", viosAdapterId)
            .get();
        return this.search(map);
    }

    public List<HmdViosVirtualCd> search(long viosId, Integer viosAdapterId,
                                         Long assignPartitionId, Integer assignAdapterId,
                                         String cdName) {
        Map<String, Object> map = MapBuilder.init()
            .put("a.vios_id", viosId)
            .put("a.vios_slot_id", viosAdapterId)
            .put("a.assign_partition_id", assignPartitionId)
            .put("a.assign_adapter_id", assignAdapterId)
            .put("a.name", cdName)
            .get();
        return this.search(map);
    }

    @Override
    public void convertInstance(final HmdViosVirtualCd srcT, final HmdViosVirtualCd desT) {
        Optional<HmdPartition> lpar = Optional.of(srcT).map(HmdViosVirtualCd::getAssignPartition).map(HmdPartition::getUuid).map(this.partitionRepository()::getByUuid);
        lpar.map(HmdPartition::getId).ifPresent(srcT::setAssignPartitionId);
        lpar.ifPresent(srcT::setAssignPartition);

        Optional<HmdViosVolumeGroup> vg = Optional.of(srcT).map(HmdViosVirtualCd::getVolumeGroup).map(HmdViosVolumeGroup::getUuid).map(this.viosVolumeGroupRepository()::getByUuid);
        vg.map(HmdViosVolumeGroup::getId).ifPresent(srcT::setVolumeGroupId);
        vg.ifPresent(srcT::setVolumeGroup);

        this.copy(srcT, desT);
    }
}
