package org.nl.acs.opc;

import cn.hutool.core.util.NumberUtil;
import lombok.extern.slf4j.Slf4j;
import org.jinterop.dcom.common.JIException;
import org.jinterop.dcom.core.*;
import org.nl.acs.device_driver.driver.ItemValue;
import org.nl.common.exception.BadRequestException;
import org.openscada.opc.lib.common.ConnectionInformation;
import org.openscada.opc.lib.da.*;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;

/**
 * @author 20220102CG\noblelift
 */
@Slf4j
public class OpcUtl {
    private static int timeout = 1 * 60 * 1000;
    private static String key = "rpc.socketTimeout";

    public static int successNum=0;
    public static int errNum=0;

    static {
        checkTimeout();
    }

    public static void checkTimeout() {
        if (Integer.getInteger(key, 0).intValue() != timeout) {
            System.setProperty(key, String.valueOf(timeout));
        }

    }


    public static void writeValue(Group group, WriteRequest... requests) throws BadRequestException {
        try {
            Map<Item, Integer> e = null;
            try {
                e = group.write(requests);
                group.write(requests);
            } catch (Exception e1) {
                try {
                    e = group.write(requests);
                } catch (Exception e2) {
                    e = group.write(requests);
                }
            }

            boolean is_success = true;
            StringBuilder message = new StringBuilder();
            Iterator arg4 = e.keySet().iterator();

            while (arg4.hasNext()) {
                Item item = (Item) arg4.next();
                Integer integer = (Integer) e.get(item);
                if (integer.intValue() != 0) {
                    if (is_success) {
                        is_success = false;
                    }

                    message.append(item.getId());
                    message.append(":error code:");
                    message.append(integer);
                    message.append("; ");
                }
            }

            if (!is_success) {
                // throw new BusinessException(message.toString());
                System.out.println("下发信号失败：" + message.toString());
                System.out.println("下发信号失败原因：" + message.toString());
                log.info("下发信号失败：" + message.toString());
                throw new BadRequestException(message.toString());
            }
        } catch (JIException arg7) {
            log.info("下发信号失败：" + arg7.getMessage());
            System.out.println("下发信号失败原因：" + arg7.getMessage());
            throw new BadRequestException(arg7.toString());
        }
    }

    public static void writeValue(Group group, ItemValue... values) throws BadRequestException {
        try {
            if (values != null && values.length > 0) {
                List<WriteRequest> ws = new ArrayList();
                ItemValue[] var3 = values;
                int var4 = values.length;

                for (int var5 = 0; var5 < var4; ++var5) {
                    ItemValue value = var3[var5];
                    Item item = group.addItem(value.getItem_code());
                    ws.add(new WriteRequest(item, getVariant(value.getItem_value())));
                }

                writeValue(group, (WriteRequest[]) ws.toArray(new WriteRequest[0]));
            }

        } catch (AddFailedException | JIException var8) {
            throw new BadRequestException(var8.toString());
        }
    }

    public static JIVariant getVariant(Object object) {
        if (object instanceof Integer) {
            return getIntegerVariant((Integer) object);
        } else if (object instanceof String) {
            return getStringVariant((String) object);
        } else if (object instanceof byte[]) {
            return getByteArrayVariant((byte[]) ((byte[]) object));
        } else if (object instanceof Byte[]) {
            return getByteArrayVariant((Byte[]) ((Byte[]) object));
        } else if (object instanceof Boolean) {
            return new JIVariant((Boolean) object);
        } else if (object instanceof int[]) {
            return getByteArrayVariantxx((int[]) ((int[]) object));
        } else if (object instanceof Integer[]) {
            JIArray array = new JIArray((Integer) object, false);
            JIVariant value = new JIVariant(array);
            return value;
        } else if (object instanceof JIVariant) {
            return (JIVariant) object;
        } else {
            throw new BadRequestException(LangProcess.msg("error_checkTypes", "int,string,byte[]"));
        }
    }

    public static Object getValue(Item item, ItemState itemState) throws BadRequestException {
        if (NumberUtil.compare(itemState.getQuality(), Short.valueOf(QualityTypeValue.OPC_QUALITY_GOOD)) != 0) {
            if (item != null) {
                log.debug("value is not good {} : {}", item.getId(), itemState.getQuality());
//                throw  new BadRequestException("值不健康进行重连!");
            } else {
                log.debug("value is not good {}", itemState.getQuality());
            }

            return null;
        } else {
            JIVariant value = itemState.getValue();
            return getValue(value, item.getId());
        }
    }

    public static Object getValue(JIVariant jiVariant, String id) throws BadRequestException {
        try {
            Object e = jiVariant.getObject();
            if (e instanceof IJIUnsigned) {
                return Integer.valueOf(((IJIUnsigned) e).getValue().intValue());
            } else if (e instanceof Boolean) {
                return jiVariant.getObjectAsBoolean() ? Integer.valueOf(1) : Integer.valueOf(0);
            } else if (e instanceof JIString) {
                return ((JIString) e).getString();
            } else if (!(e instanceof JIArray)) {
                if (e instanceof Integer) {
                    return jiVariant.getObject();
                } else if (e instanceof Short) {
                    return jiVariant.getObject();
                } else if (e instanceof Float) {
                    return jiVariant.getObject();
                } else if (e instanceof Double) {
                    return jiVariant.getObject();
                } else {
                    System.err.println(id + "不明类型" + e.getClass());
                    if (jiVariant.getType() == 0) {
                        System.err.println("因类型为emtpy 返回 null");
                        return null;
                    } else if (jiVariant.getType() == 1) {
                        System.err.println("因类型为null 返回 null");
                        return null;
                    } else {
                        return jiVariant.getObject();
                    }
                }
            } else {
                Class clazz = ((JIArray) e).getArrayClass();
                int[] r;
                int i;
                if (JIUnsignedByte.class.isAssignableFrom(clazz)) {
                    JIUnsignedByte[] arg7 = (JIUnsignedByte[]) ((JIUnsignedByte[]) ((JIArray) e).getArrayInstance());
                    r = new int[arg7.length];

                    for (i = 0; i < arg7.length; ++i) {
                        r[i] = arg7[i].getValue().byteValue();
                    }

                    return r;
                } else if (!JIUnsignedShort.class.isAssignableFrom(clazz)) {
                    System.err.println(id + "不明类型");
                    if (jiVariant.getType() == 0) {
                        System.err.println("因类型为emtpy 返回 null");
                        return null;
                    } else if (jiVariant.getType() == 1) {
                        System.err.println("因类型为null 返回 null");
                        return null;
                    } else {
                        return ((JIArray) e).getArrayInstance();
                    }
                } else {
                    JIUnsignedShort[] array = (JIUnsignedShort[]) ((JIUnsignedShort[]) ((JIArray) e)
                            .getArrayInstance());
                    r = new int[array.length];

                    for (i = 0; i < array.length; ++i) {
                        r[i] = array[i].getValue().intValue();
                    }

                    return r;
                }
            }
        } catch (JIException e) {
            throw new BadRequestException(e.getMessage());
        }
    }


    public static Server getServer(String host, String clsid, String user, String password, String domain)
            throws BadRequestException {
        checkTimeout();
        Server server = null;

        try {
            server = new Server(getConnection(host, clsid, user, password, domain),
                    Executors.newSingleThreadScheduledExecutor());
            server.connect();
            successNum++;
            return server;
        } catch (Exception e) {
            errNum++;
            throw new BadRequestException(e.getMessage());
        }finally{
            log.info("successNum:"+successNum);
            log.info("errNum:"+errNum);
        }
    }

    public static Server getAutoServer(String host, String clsid, String user, String password, String domain) throws BadRequestException {
        checkTimeout();
        Server server = null;
        server = new Server(getConnection(host, clsid, user, password, domain), Executors.newSingleThreadScheduledExecutor());
        AutoReconnectController autoReconnectController = new AutoReconnectController(server);
        autoReconnectController.connect();
        return server;
    }

    public static ConnectionInformation getConnection(String host, String clsid, String user, String password,
                                                      String domain) {
        ConnectionInformation connection = new ConnectionInformation();
        connection.setHost(host);
        connection.setClsid(clsid);
        connection.setUser(user);
        connection.setPassword(password);
        connection.setDomain(domain);
        return connection;
    }

    public static JIVariant getByteArrayVariantxx(int[] bytes) {
        Integer[] byte_Data = new Integer[bytes.length];

        for (int i = 0; i < bytes.length; ++i) {
            byte_Data[i] = bytes[i];
        }

        JIArray array = new JIArray(byte_Data, false);
        JIVariant value = new JIVariant(array);
        return value;
    }

    public static JIVariant getIntegerVariant(Integer integer) {
        return new JIVariant(integer);
    }

    public static JIVariant getStringVariant(String string) {
        return new JIVariant(string);
    }

    public static JIVariant getByteArrayVariant(byte[] bytes) {
        Byte[] byte_Data = new Byte[bytes.length];

        for (int i = 0; i < bytes.length; ++i) {
            byte_Data[i] = bytes[i];
        }

        JIArray array = new JIArray(byte_Data, false);
        JIVariant value = new JIVariant(array);
        return value;
    }

    public static JIVariant getByteArrayVariant(Byte[] bytes) {
        JIArray array = new JIArray(bytes, false);
        JIVariant value = new JIVariant(array);
        return value;
    }


}

