package org.nl.acs.opc;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.nl.acs.auto.initial.ApplicationAutoInitial;
import org.nl.acs.device.domain.Device;
import org.nl.acs.device.enums.DeviceType;
import org.nl.acs.device.service.DeviceDriverDefinationAppService;
import org.nl.acs.device_driver.DeviceDriver;
import org.nl.acs.device_driver.DeviceDriverDefination;
import org.nl.acs.device_driver.LinewayDeviceDriver;
import org.nl.acs.device_driver.driver.OpcDeviceDriver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @author 20220102CG\noblelift
 */
@Slf4j
@Service
public class DeviceAppServiceImpl implements DeviceAppService, ApplicationAutoInitial {
    /**
     * 所有设备链表
     */
    private List<Device> devices = new ArrayList();
    /**
     * 设备对应的下表
     */
    private List<String> code_indexs = new ArrayList();
    @Autowired
    private DeviceManageService deviceManageService;
    @Autowired
    private DeviceDriverDefinationAppService deviceDriverDefinationAppService;

    @Override
    public List<Device> findAllDevice() {
        return devices;
    }

    @Override
    public Device findDeviceByCode(String device_code) {
        Iterator var2 = this.findAllDevice().iterator();

        Device device;
        do {
            if (!var2.hasNext()) {
                return null;
            }

            device = (Device) var2.next();
        } while (!StrUtil.equals(device.getDevice_code(), device_code));

        return device;
    }

    @Override
    public Device findDeviceByAddress(String address) {
        Iterator var2 = this.findAllDevice().iterator();

        Device device;
        do {
            if (!var2.hasNext()) {
                return null;
            }

            device = (Device) var2.next();
        } while (!StrUtil.equals(device.getAddress(), address));

        return device;
    }

    @Override
    public int deviceSize() {
        return this.findAllDevice().size();
    }

    @Override
    public Map<String, List<List<OpcItemDto>>> findAllFormatProtocolFromDriver() {
        Map<String, List<List<OpcItemDto>>> result = new LinkedHashMap();
        List<OpcItemDto> dtos = new ArrayList();
        List<OpcDeviceDriver> opcDrivers = this.findDeviceDriver(OpcDeviceDriver.class);
        Iterator var4 = opcDrivers.iterator();
        while (var4.hasNext()) {
            OpcDeviceDriver opcDriver = (OpcDeviceDriver) var4.next();
            List<OpcItemDto> items = opcDriver.getOpcItems();
            if (items != null && items.size() > 0) {
                dtos.addAll(items);
            }
        }

        Map<String, List<OpcItemDto>> map = new HashMap();
        List<String> servers = new ArrayList();
        Iterator var18 = dtos.iterator();

        ArrayList serverResult;
        while (var18.hasNext()) {
            OpcItemDto dto = (OpcItemDto) var18.next();

            if (!StrUtil.isEmpty(dto.getOpc_plc_code())) {
                if (!servers.contains(dto.getOpc_plc_code())) {
                    serverResult = new ArrayList();
                    serverResult.add(dto);
                    map.put(dto.getOpc_plc_code(), serverResult);
                    servers.add(dto.getOpc_plc_code());
                } else {
                    ((List) map.get(dto.getOpc_plc_code())).add(dto);
                }
            }
        }
        var18 = map.keySet().iterator();

        while (var18.hasNext()) {
            String serverCode = (String) var18.next();
            serverResult = new ArrayList();
            Map<String, List<OpcItemDto>> deviceMap = new HashMap();
            List<OpcItemDto> devices = (List) map.get(serverCode);
            List<String> deviceStrings = new ArrayList();
            Iterator var12 = devices.iterator();

            while (var12.hasNext()) {
                OpcItemDto dto = (OpcItemDto) var12.next();
                if (!deviceStrings.contains(dto.getDevice_code())) {
                    List<OpcItemDto> temp = new ArrayList();
                    temp.add(dto);
                    deviceMap.put(dto.getDevice_code(), temp);
                    deviceStrings.add(dto.getDevice_code());
                } else {
                    ((List) deviceMap.get(dto.getDevice_code())).add(dto);
                }
            }
            List<OpcItemDto> temp = new ArrayList();
            Iterator var21 = deviceMap.keySet().iterator();

            while (var21.hasNext()) {
                String string = (String) var21.next();
                List<OpcItemDto> device = (List) deviceMap.get(string);
                if (temp.size() + device.size() > WcsConfig.opc_group_sync_max_item) {
                    if (temp.size() > 0) {
                        serverResult.add(temp);
                        temp = new ArrayList();
                        temp.addAll(device);
                    } else {
                        serverResult.add(device);
                    }
                } else {
                    temp.addAll(device);
                }
            }
            serverResult.add(temp);
            result.put(serverCode, serverResult);


        }

        return result;
    }

    @Override
    public Map<String, List<List<OpcItemDto>>> findAllFormatProtocolFromDriverByPlc() {
        Map<String, List<List<OpcItemDto>>> result = new LinkedHashMap();
        List<OpcItemDto> dtos = new ArrayList();
        List<OpcDeviceDriver> opcDrivers = this.findDeviceDriver(OpcDeviceDriver.class);
        Iterator var4 = opcDrivers.iterator();

        while (var4.hasNext()) {
            OpcDeviceDriver opcDriver = (OpcDeviceDriver) var4.next();
            List<OpcItemDto> items = opcDriver.getOpcItems();
            if (items != null && items.size() > 0) {
                dtos.addAll(items);
            }
        }

        Map<String, List<OpcItemDto>> map = new HashMap();
        List<String> servers = new ArrayList();
        Iterator var18 = dtos.iterator();

        ArrayList serverResult;
        while (var18.hasNext()) {
            OpcItemDto dto = (OpcItemDto) var18.next();
            if (!StrUtil.isEmpty(dto.getOpc_plc_code())) {
                if (!servers.contains(dto.getOpc_plc_code())) {
                    serverResult = new ArrayList();
                    serverResult.add(dto);
                    map.put(dto.getOpc_plc_code(), serverResult);
                    servers.add(dto.getOpc_plc_code());
                } else {
                    ((List) map.get(dto.getOpc_plc_code())).add(dto);
                }
            }
        }

        var18 = map.keySet().iterator();

        while (var18.hasNext()) {
            String serverCode = (String) var18.next();
            serverResult = new ArrayList();
            Map<String, List<OpcItemDto>> deviceMap = new HashMap();
            List<OpcItemDto> devices = (List) map.get(serverCode);
            List<String> deviceStrings = new ArrayList();
            Iterator var12 = devices.iterator();

            while (var12.hasNext()) {
                OpcItemDto dto = (OpcItemDto) var12.next();
                if (!deviceStrings.contains(dto.getDevice_code())) {
                    List<OpcItemDto> temp = new ArrayList();
                    temp.add(dto);
                    deviceMap.put(dto.getDevice_code(), temp);
                    deviceStrings.add(dto.getDevice_code());
                } else {
                    ((List) deviceMap.get(dto.getDevice_code())).add(dto);
                }
            }

            List<OpcItemDto> temp = new ArrayList();
            Iterator var21 = deviceMap.keySet().iterator();

            while (var21.hasNext()) {
                String string = (String) var21.next();
                List<OpcItemDto> device = (List) deviceMap.get(string);
                if (temp.size() + device.size() > WcsConfig.opc_group_sync_max_item) {
                    if (temp.size() > 0) {
                        serverResult.add(temp);
                        temp = new ArrayList();
                        temp.addAll(device);
                    } else {
                        serverResult.add(device);
                    }
                } else {
                    temp.addAll(device);
                }
            }

            serverResult.add(temp);
            result.put(serverCode, serverResult);
        }

        return result;
    }


    @Override
    public <T extends DeviceDriver> List<T> findDeviceDriver(Class<T> clazz) {
        List<T> list = new ArrayList<>();
        List<Device> devices = new CopyOnWriteArrayList<>(this.findAllDevice());

        for (Device device : devices) {
            DeviceDriver deviceDriver = device.getDeviceDriver();
            // 查找某驱动的所有子类
            if (deviceDriver != null && clazz.isAssignableFrom(deviceDriver.getClass())) {
                list.add((T) device.getDeviceDriver());
            }
        }

        return list;
    }

    @Override
    public Map<String, String> findDeviceOptions(DeviceType deviceType) {
        List<Device> list = this.findDevice(deviceType);
        Map<String, String> map = new HashMap();
        Iterator var4 = list.iterator();

        while (var4.hasNext()) {
            Device device = (Device) var4.next();
            map.put(device.getDevice_code(), device.getDevice_name());
        }
        return map;
    }


    @Override
    public List<Device> findDeviceByType(DeviceType deviceType) {
        List<Device> list = this.findDevice(deviceType);
        Map<String, String> map = new HashMap();
        Iterator var4 = list.iterator();

        while (var4.hasNext()) {
            Device device = (Device) var4.next();
            list.add(device);
        }
        return list;
    }


    @Override
    public List<Device> findDevice(DeviceType deviceType) {
        List<Device> list = new ArrayList();
        Iterator var3 = this.devices.iterator();

        while (var3.hasNext()) {
            Device device = (Device) var3.next();
            if (ObjectUtil.equal(device.getDevice_type(), deviceType.name())) {
                list.add(device);
            }
        }
        return list;
    }

    @Override
    public String findDeviceTypeByCode(String deviceCode) {
        Iterator var3 = this.devices.iterator();

        while (var3.hasNext()) {
            Device device = (Device) var3.next();
            if (ObjectUtil.equal(device.getDevice_code(), deviceCode) && ObjectUtil.isNotEmpty(device.getDeviceDriverDefination())) {
                return device.getDeviceDriverDefination().getFitDeviceTypes().get(0).name();
            }
        }
        return null;
    }

    @Override
    public List<LinewayDeviceDriver> findLaneway() {
        return this.findDeviceDriver(LinewayDeviceDriver.class);
    }

    @Override
    public void autoInitial() throws Exception {
        log.info("加载所有设备");
        this.reload();
    }

    @Override
    public synchronized void reload() {
        List<DeviceManageDto> deviceManageDtos = deviceManageService.queryAllWithExtra();
        this.devices = new ArrayList();
        Collections.synchronizedList(this.devices);
        this.code_indexs = new ArrayList();
        Collections.synchronizedList(this.code_indexs);
        int i = 0;

        for (int size = deviceManageDtos.size(); i < size; ++i) {
            DeviceManageDto deviceManage = (DeviceManageDto) deviceManageDtos.get(i);
            Device device = new Device();
            BeanUtil.copyProperties(deviceManage, device);
            this.devices.add(device);
            this.code_indexs.add(device.getDevice_code());

            if (!StrUtil.isEmpty(device.getDriver_code())) {
                DeviceDriverDefination defination = this.deviceDriverDefinationAppService.getDeviceDriverDefination(deviceManage.getDriver_code());
                if (defination != null) {
                    device.setDeviceDriverDefination(defination);
                    DeviceDriver driver = defination.getDriverInstance(device);
                    device.setDeviceDriver(driver);

                }
            }

        }

    }

    @Override
    public void removeDevice(String deviceCode) {

        Iterator<Device> iterator = devices.iterator();
        while (iterator.hasNext()) {
            Device device = iterator.next();
            if (StrUtil.equals(device.getDevice_code(), deviceCode)) {
                iterator.remove();
            }
        }
        Iterator<String> iterator2 = code_indexs.iterator();
        while (iterator2.hasNext()) {
            String str = iterator2.next();
            if (StrUtil.equals(str, deviceCode)) {
                iterator2.remove();
            }
        }

    }

    @Override
    public void addDevice(String deviceCode) {
        List<DeviceManageDto> deviceManageDtos = this.deviceManageService.queryAllWithExtra(deviceCode);
        int i = 0;

        for (int size = deviceManageDtos.size(); i < size; ++i) {
            DeviceManageDto deviceManage = (DeviceManageDto) deviceManageDtos.get(i);
            Device device = new Device();
            BeanUtil.copyProperties(deviceManage, device);
            this.devices.add(device);
            this.code_indexs.add(device.getDevice_code());

            if (!StrUtil.isEmpty(device.getDriver_code())) {
                DeviceDriverDefination defination = this.deviceDriverDefinationAppService.getDeviceDriverDefination(deviceManage.getDriver_code());
                if (defination != null) {
                    device.setDeviceDriverDefination(defination);
                    DeviceDriver driver = defination.getDriverInstance(device);
                    device.setDeviceDriver(driver);

                }
            }

        }
    }

    @Override
    public TreeSet<Integer> selectRegion() {
        TreeSet<Integer> set = new TreeSet<>();
        for (Device device : devices) {
            set.add(Integer.parseInt(StrUtil.isEmpty(device.getRegion()) ? "0" : device.getRegion()));
        }
        return set;
    }

}
