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.HmdViosVirtualDisk;
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 HmdViosVirtualDiskRepository extends HmdGenericDao<HmdViosVirtualDisk> {

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

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

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

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

    public HmdViosVirtualDisk 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 HmdViosVirtualDisk getById(long id) {
        return this.search(Collections.singletonMap("a.id", id)).stream().findFirst().orElse(null);
    }

    public List<HmdViosVirtualDisk> 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<HmdViosVirtualDisk> search(long viosId, Integer viosAdapterId,
                                           Long assignPartitionId, Integer assignAdapterId,
                                           Long volumeGroupId, String diskName) {
        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.volume_group_id", volumeGroupId)
            .put("a.name", diskName)
            .get();
        return this.search(map);
    }

    @Override
    public void convertInstance(final HmdViosVirtualDisk srcT, final HmdViosVirtualDisk desT) {
        Optional<HmdPartition> lpar = Optional.of(srcT).map(HmdViosVirtualDisk::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(HmdViosVirtualDisk::getVolumeGroup).map(HmdViosVolumeGroup::getUuid).map(this.viosVolumeGroupRepository()::getByUuid);
        vg.map(HmdViosVolumeGroup::getId).ifPresent(srcT::setVolumeGroupId);
        vg.ifPresent(srcT::setVolumeGroup);

        this.copy(srcT, desT);
    }
}
