package com.imdroid.sideslope.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.imdroid.secapi.dto.GnssDevice;
import com.imdroid.secapi.dto.GnssDeviceMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author Layton
 * @date 2023/2/3 20:46
 */
@Component
public class LocalDeviceServiceImpl implements DeviceService {
    @Autowired
    private GnssDeviceMapper gnssDeviceMapper;

    private static final Cache<String, Device> deviceCache = CacheBuilder.newBuilder().
            expireAfterAccess(20, TimeUnit.MINUTES).build();

    private static final Cache<String, List<Device>> subDeviceCache = CacheBuilder.newBuilder().
            expireAfterAccess(10, TimeUnit.MINUTES).build();

    Device getDeviceFromDB(String deviceId){
        GnssDevice gnssDevice = gnssDeviceMapper.queryByDeviceId(deviceId);
        if (gnssDevice == null) {
            return null;
        }
        Device device = new Device();
        device.setTenantId(gnssDevice.getTenantid());
        device.setDeviceId(gnssDevice.getDeviceid());
        device.setDeviceType(gnssDevice.getDevicetype());
        device.setModel(gnssDevice.getModel());
        device.setParentId(gnssDevice.getParentid());
        device.setName(gnssDevice.getName());
        device.setProjectId(gnssDevice.getProject_id());
        device.setCalcGroupId(gnssDevice.getCalc_group_id());
        device.setBasicGroupId(gnssDevice.getGroup_id());
        device.setOpMode(gnssDevice.getOpmode());
        device.setFwdId(gnssDevice.getFwd_group_id());
        device.setIPose(gnssDevice.getIpose());
        device.setIPosn(gnssDevice.getIposn());
        device.setIPosd(gnssDevice.getIposd());
        device.setEcefx(gnssDevice.getEcefx());
        device.setEcefy(gnssDevice.getEcefy());
        device.setEcefz(gnssDevice.getEcefz());
        device.setLoggingmode(gnssDevice.getLoggingmode());
        device.setParentId1(gnssDevice.getParentid1());
        return device;
    }

    public List<Device> getDeviceListFromDBByParentId(String parentId) {
        QueryWrapper<GnssDevice> query = new QueryWrapper();
        query.eq("parentid", parentId);
        List<GnssDevice> gnssDeviceList = gnssDeviceMapper.selectList(query);
        List<Device> deviceList = new ArrayList<>(gnssDeviceList.size());
        for (GnssDevice gnssDevice : gnssDeviceList) {
            Device device = findByDeviceId(gnssDevice.getDeviceid());
            if(device!=null) deviceList.add(device);
        }
        return deviceList;
    }

    public List<Device> getDeviceListFromDBByParentId1(String parentId1) {
        QueryWrapper<GnssDevice> query = new QueryWrapper();
        query.eq("parentid1", parentId1);
        List<GnssDevice> gnssDeviceList = gnssDeviceMapper.selectList(query);
        List<Device> deviceList = new ArrayList<>(gnssDeviceList.size());
        for (GnssDevice gnssDevice : gnssDeviceList) {
            Device device = findByDeviceId(gnssDevice.getDeviceid());
            if(device!=null) deviceList.add(device);
        }
        return deviceList;
    }

    @Override
    public Device findByDeviceId(String deviceId) {
        Device device = deviceCache.getIfPresent(deviceId);
        if (device == null) {
            device = getDeviceFromDB(deviceId);
            if (device != null) {
                deviceCache.put(deviceId, device);
            }
        }
        return device;
    }

    @Override
    public List<Device> findByParentId(String parentId) {
        String cacheKey = "PARENTID_" + parentId;
        List<Device> devices = subDeviceCache.getIfPresent(cacheKey);
        if (devices == null) {
            devices = getDeviceListFromDBByParentId(parentId);
            if (devices != null) {
                subDeviceCache.put(cacheKey, devices);
            }
        }
        return devices;
    }

    @Override
    public List<Device> findByParentId1(String parentId1) {
        String cacheKey = "PARENTID1_" + parentId1;
        List<Device> devices = subDeviceCache.getIfPresent(cacheKey);
        if (devices == null) {
            devices = getDeviceListFromDBByParentId1(parentId1);
            if (devices != null) {
                subDeviceCache.put(cacheKey, devices);
            }
        }
        return devices;
    }

    public void refresh(String deviceId, String oldParentId, String oldParentId1){
        Device device = deviceCache.getIfPresent(deviceId);
        if (device != null) {
            if(device.getParentId()!=null) {
                subDeviceCache.invalidate("PARENTID_" + device.getParentId());
                if(oldParentId!=null && !oldParentId.equals(device.getParentId())){
                    subDeviceCache.invalidate("PARENTID_" + oldParentId);
                }
            }
            if(device.getParentId1()!=null) {
                subDeviceCache.invalidate("PARENTID1_" + device.getParentId1());
                if(oldParentId1!=null && !oldParentId1.equals(device.getParentId1())){
                    subDeviceCache.invalidate("PARENTID1_" + oldParentId1);
                }
            }
            deviceCache.invalidate(deviceId);
        }
    }
}
