package com.eactive.eai.rms.onl.dashboard.modern.backup.mapper;

import com.eactive.eai.rms.onl.dashboard.modern.backup.BackupContentVO;
import com.eactive.eai.rms.onl.server.repository.ExpiringMap;
import com.eactive.eai.rms.onl.server.repository.Repository;
import com.eactive.eai.rms.onl.vo.MonitorDataVo;
import org.apache.commons.collections.keyvalue.MultiKey;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

public class RepositoryVoMapper implements BackupMapper<BackupContentVO.RepositoryFields, Repository> {

    @Override
    public BackupContentVO.RepositoryFields toVo(Repository repository) throws Exception {

        BackupContentVO.RepositoryFields result = new BackupContentVO.RepositoryFields();

        Field fRepository = Repository.class.getDeclaredField("repository");
        fRepository.setAccessible(true);
        ExpiringMap<MultiKey, MonitorDataVo> vRepository = (ExpiringMap<MultiKey, MonitorDataVo>) fRepository.get(repository);

        Map<String, MonitorDataVo> v2Repository = multiKeyToNormalMap(vRepository);
        result.setRepository(v2Repository);

        Field fRepositoryNoExpire = Repository.class.getDeclaredField("repositoryNoExpire");
        fRepositoryNoExpire.setAccessible(true);
        ConcurrentHashMap<MultiKey, MonitorDataVo> vRepositoryNoExpire = (ConcurrentHashMap<MultiKey, MonitorDataVo>) fRepositoryNoExpire.get(repository);

        ConcurrentHashMap<String, MonitorDataVo> v2RepositoryNoExpire = multiKeyToNormalMap(vRepositoryNoExpire);

        result.setRepositoryNoExpire(v2RepositoryNoExpire);

        return result;
    }

    @Override
    public void setVoValuesToObject(BackupContentVO.RepositoryFields vo, Repository object) throws Exception {

        ExpiringMap<MultiKey, Object> vRepository = new ExpiringMap<>();
        vo.getRepository().entrySet().stream()
                .forEach(e -> {
                    String[] splitted = e.getKey().split("_");
                    vRepository.put(new MultiKey(splitted), e.getValue());
                });

        Field fRepository = Repository.class.getDeclaredField("repository");
        fRepository.setAccessible(true);
        fRepository.set(object, vRepository);

        ConcurrentHashMap<MultiKey, Object> vRepositoryNoExpire = new ConcurrentHashMap<>();
        vo.getRepositoryNoExpire().entrySet().stream()
                .forEach(e -> {
                    String[] splitted = e.getKey().split("_");
                    vRepositoryNoExpire.put(new MultiKey(splitted), e.getValue());
                });

        Field fRepositoryNoExpire = Repository.class.getDeclaredField("repositoryNoExpire");
        fRepositoryNoExpire.setAccessible(true);
        fRepositoryNoExpire.set(object, vRepositoryNoExpire);
    }

    private <T> ConcurrentHashMap<String, T> multiKeyToNormalMap(Map<MultiKey, T> vRepository) {
        if (vRepository == null)
            return null;

        return vRepository.entrySet().stream()
                .collect(Collectors.toMap(
                        e -> Arrays.stream(e.getKey().getKeys())
                                .map(Object::toString)
                                .collect(Collectors.joining("_")),
                        Map.Entry::getValue, (oldVal, newVal) -> newVal, ConcurrentHashMap::new
                ));
    }

}
