package cn.reghao.oss.store.config.spring;

import cn.reghao.jutil.jdk.serializer.JsonConverter;
import cn.reghao.jutil.jdk.store.LocalStores;
import cn.reghao.jutil.jdk.store.SubDirCount;
import cn.reghao.oss.sdk.OssConsoleClient;
import cn.reghao.oss.store.api.dto.ObjectChannel;
import cn.reghao.oss.store.api.dto.StoreDiskDto;
import cn.reghao.oss.store.api.dto.StoreNodeDto;
import cn.reghao.oss.store.api.dto.StoreProperties;
import cn.reghao.oss.store.config.SpringProperties;
import cn.reghao.oss.store.db.mapper.DataBlockMapper;
import cn.reghao.oss.store.service.StoreChannelService;
import cn.reghao.oss.store.service.StoreLocalCache;
import cn.reghao.oss.store.task.FileTask;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author reghao
 * @date 2022-03-23 09:22:01
 */
@Slf4j
@Component
public class AppLifecycle implements ApplicationRunner, DisposableBean {
    private final DataBlockMapper dataBlockMapper;
    private final FileTask fileTask;
    private final SpringProperties springProperties;
    private final OssConsoleClient ossConsoleClient;
    private final StoreLocalCache storeLocalCache;
    private final StoreChannelService storeChannelService;

    public AppLifecycle(DataBlockMapper dataBlockMapper, FileTask fileTask, SpringProperties springProperties,
                        OssConsoleClient ossConsoleClient, StoreLocalCache storeLocalCache,
                        StoreChannelService storeChannelService) {
        this.dataBlockMapper = dataBlockMapper;
        this.fileTask = fileTask;
        this.springProperties = springProperties;
        this.ossConsoleClient = ossConsoleClient;
        this.storeLocalCache = storeLocalCache;
        this.storeChannelService = storeChannelService;
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        initLocalStore();
        initStoreNode();
        log.info("执行文件任务...");
        fileTask.exec();
        log.info("文件任务执行完成...");
    }

    private void initLocalStore() throws IOException {
        log.info("初始化本地磁盘...");
        List<String> diskDirs = springProperties.getDiskDirs();
        for (String diskDir : diskDirs) {
            File dir = new File(diskDir);
            if (!dir.exists()) {
                dir.mkdirs();
            }
        }
        LocalStores.init(diskDirs);

        for (String diskDir : diskDirs) {
            Map<String, Integer> map = new HashMap<>();
            /*List<SubDirCount> list = dataBlockMapper.findSubDirCount("");
            list.forEach(subDirCount -> {
                String relativeDir = subDirCount.getRelativeDir();
                String storeDir = diskDir + relativeDir;
                File file = new File(storeDir);

                int total = subDirCount.getTotal();
                map.put(file.getAbsolutePath(), total);
            });*/

            LocalStores.initStoreDirs(diskDir, map);
        }
        log.info("本地磁盘数据初始化完成...");
    }

    private void initStoreNode() throws Exception {
        log.info("初始化 StoreNode...");
        List<StoreDiskDto> list = storeLocalCache.getStoreDisks();
        String nodeAddr = springProperties.getHost();
        int httpPort = springProperties.getHttpPort();
        int rpcPort = springProperties.getRpcPort();
        StoreNodeDto storeNodeDto = new StoreNodeDto(nodeAddr, httpPort, rpcPort, list);
        String jsonPayload = JsonConverter.objectToJson(storeNodeDto);
        ossConsoleClient.registerNode(jsonPayload);

        StoreProperties storeProperties = ossConsoleClient.getStoreProperties(nodeAddr);
        List<ObjectChannel> objectChannels = ossConsoleClient.getObjectChannels(nodeAddr);
        storeLocalCache.initOssStore(storeProperties);
        storeChannelService.initChannels(objectChannels);
        log.info("StoreNode 初始化完成...");
    }

    @Override
    public void destroy() {
    }
}
