package com.lanyuanxiaoyao.service.queue.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.lanyuanxiaoyao.service.queue.configuration.AutoSaveProperties;
import com.lanyuanxiaoyao.service.queue.configuration.Constants;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

/**
 * 自动保存
 *
 * @author lanyuanxiaoyao
 * @date 2023-05-06
 */
@Service
public class AutoSaveService {
    private static final Logger logger = LoggerFactory.getLogger(AutoSaveService.class);

    private final AutoSaveProperties autoSaveProperties;
    private final Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder;

    public AutoSaveService(AutoSaveProperties autoSaveProperties, Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder) {
        this.autoSaveProperties = autoSaveProperties;
        this.jackson2ObjectMapperBuilder = jackson2ObjectMapperBuilder;
    }

    @Scheduled(fixedDelay = 60, initialDelay = 60, timeUnit = TimeUnit.SECONDS)
    public void autoSave() throws IOException {
        // 用单独的变量确认是否开始自动保存，保证自动保存在初始化加载完后再启动，防止把空数据覆盖保存文件
        if (Constants.AUTO_SAVE.get()) {
            if (autoSaveProperties.getLocation() != null && !"".equals(autoSaveProperties.getLocation())) {
                save(Constants.DEQUE_MAP, Constants.DEQUE_SAVE_FILENAME);
                save(Constants.QUEUE_MAP, Constants.QUEUE_SAVE_FILENAME);
                return;
            }
            logger.warn("Save path is not set");
        }
    }

    private void save(Map<String, ? extends Queue<?>> o, String name) throws IOException {
        if (o == null || o.isEmpty()) {
            return;
        }
        Map<String, List<?>> map = new HashMap<>(o.size());
        o.forEach((k, q) -> map.put(k, new ArrayList<>(o.get(k))));

        Files.createDirectories(Paths.get(autoSaveProperties.getLocation()));
        Path saveDataPath = Paths.get(autoSaveProperties.getLocation(), name);
        ObjectMapper mapper = jackson2ObjectMapperBuilder.build();
        String data = mapper.writeValueAsString(map);

        map.clear();

        data = URLEncoder.encode(data, "utf-8");
        Files.write(saveDataPath, data.getBytes());
    }
}
