package com.ycwl.basic.device.operator;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ycwl.basic.device.entity.common.FileObject;
import com.ycwl.basic.device.entity.wvp_passive.WvpPassiveStorageConfig;
import com.ycwl.basic.storage.utils.StorageUtil;
import com.ycwl.basic.utils.SnowFlakeUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
public class WvpPassiveStorageOperator extends ADeviceStorageOperator {

    public static class Task {
        public Long taskId;
        public Long scenicId;
        public Long deviceId;
        public String deviceNo;
        @JSONField(format = "yyyy-MM-dd HH:mm:ss")
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
        public Date startTime;
        @JSONField(format = "yyyy-MM-dd HH:mm:ss")
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
        public Date endTime;
    }

    private static List<Task> taskList = new CopyOnWriteArrayList<>();
    private static ConcurrentHashMap<Long, FileObject> fileListMap = new ConcurrentHashMap<>();
    private static RedisTemplate<String, String> redisTemplate = null;
    private static final String TASK_KEY = "wvp:task:s%s:d%s:";

    private WvpPassiveStorageConfig config;

    public WvpPassiveStorageOperator(String configJson) {
        loadConfig(configJson);
    }


    public static void setRedisTemplate(RedisTemplate<String, String> redisTemplate) {
        WvpPassiveStorageOperator.redisTemplate = redisTemplate;
    }

    public static void onReceiveResult(Long taskId, FileObject fileObject) {
        if (fileObject == null) {
            log.info("任务{}获取视频失败！", taskId);
            fileListMap.put(taskId, new FileObject());
        } else {
            fileListMap.put(taskId, fileObject);
        }
    }

    public static List<Task> getTaskListByScenicId(Long scenicId) {
        List<Task> scenicTask = taskList.stream().filter(task -> task.scenicId.equals(scenicId)).collect(Collectors.toList());
        if (scenicTask.isEmpty()) {
            return Collections.emptyList();
        }
        taskList.removeAll(scenicTask);
        return scenicTask;
    }

    @Override
    public void loadConfig(String configJson) {
        this.config = JSON.parseObject(configJson, WvpPassiveStorageConfig.class);
    }

    @Override
    public List<FileObject> getFileListByDtRange(Date startDate, Date endDate) {
        Task task = new Task();
        task.taskId = SnowFlakeUtil.getLongId();
        task.scenicId = device.getScenicId();
        task.deviceId = device.getId();
        if (StringUtils.isNotBlank(config.getDeviceNo())) {
            task.deviceNo = config.getDeviceNo();
        } else {
            task.deviceNo = device.getNo2();
        }
        task.startTime = startDate;
        task.endTime = endDate;
        if (redisTemplate == null) {
            taskList.add(task);
        } else {
            redisTemplate.opsForValue().set(String.format(TASK_KEY, task.scenicId, task.deviceNo) + task.taskId, JSON.toJSONString(task), 10 * 60L, TimeUnit.SECONDS);
        }
        Date taskStartTime = new Date();
        while (true) {
            if (new Date().getTime() - taskStartTime.getTime() > 60000L) {
                log.info("任务{}获取视频超时！", task.taskId);
                fileListMap.remove(task.taskId);
                return Collections.emptyList();
            }
            if (fileListMap.containsKey(task.taskId)) {
                FileObject fileObject = fileListMap.get(task.taskId);
                if (StringUtils.isNotBlank(fileObject.getUrl())) {
                    log.info("任务{}获取视频成功！{}", task.taskId, fileObject);
                    fileListMap.remove(task.taskId);
                    fileObject.setExact(true);
                    return Collections.singletonList(fileObject);
                } else {
                    log.info("任务{}获取视频失败！", task.taskId);
                    return Collections.emptyList();
                }
            } else {
                try {
                    //noinspection BusyWait 得等待
                    Thread.sleep(1000L);
                } catch (InterruptedException e) {
                    return Collections.emptyList();
                }
            }
        }
    }

    @Override
    public boolean removeFilesBeforeDate(Date date) {
        // 不做删除
        return false;
    }
}
