package org.nl.acs.device_driver.driver;

import lombok.extern.slf4j.Slf4j;
import org.nl.acs.opc.*;
import org.nl.acs.udw.UnifiedDataAccessor;
import org.nl.acs.udw.UnifiedDataAccessorFactory;
import org.nl.acs.udw.UnifiedDataAppService;
import org.nl.config.SpringContextHolder;
import org.openscada.opc.lib.da.Group;
import org.openscada.opc.lib.da.Item;
import org.openscada.opc.lib.da.ItemState;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;

@Slf4j
public class AbstractOpcDeviceDriver extends AbstractDeviceDriver implements OpcDeviceDriver {
  UnifiedDataAccessor opcUdw;

  private OpcServerService opcServerService = SpringContextHolder.getBean(OpcServerService.class);

  public AbstractOpcDeviceDriver() {
    this.opcUdw = UnifiedDataAccessorFactory.getAccessor(OpcConfig.udw_opc_value_key);
  }


  private Date sendTime;
  private String last_items;
  private int noLog_sendTimeOut;
  private Date noLog_sendTime;
  private String noLog_last_items;

  @Override
  public UnifiedDataAccessor getOpcValueAccessor() {
    return this.opcUdw;
  }


  public  void checkcontrol(Map<String, Object> itemValues) throws Exception {
    Group group = opcServerService.getServer(this.getOpcServer());
    Map<String, Object> write = new HashMap();
    Map<String, Item> readitems = new LinkedHashMap();
    List<String> itemsString = new ArrayList();
    itemsString = new ArrayList<> (itemValues.keySet());
    Iterator is = itemsString.iterator();

    while (is.hasNext()) {
      String string = (String) is.next();
      try {
        readitems.put(string, group.addItem(string));
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
    int i = 0;
    while(true) {
      //下发信号
      control( itemValues);
      Map<String, Object> read = new HashMap();
      Map<Item, ItemState> itemStatus = group.read(true, (Item[])readitems.values().toArray(new Item[0]));
      Set<Item> items = itemStatus.keySet();
      Iterator var15 = items.iterator();

      while(var15.hasNext()) {
        Item item = (Item)var15.next();
        ItemState itemState = (ItemState)itemStatus.get(item);
        Object value = OpcUtl.getValue(item, itemState);
        read.put(item.getId(), value);
      }

      boolean check = true;
      Iterator var24 = itemsString.iterator();

      while(var24.hasNext()) {
        String itemString = (String)var24.next();
        if (!ObjectUtl.isEquals(itemValues.get(itemString), JsonUtl.parse(read.get(itemString)))) {
          check = false;
        }
      }
      if (check) {
        return;
      }

      if (i > 0) {
        ThreadUtl.sleep(300L);
      }

      if (i > 3) {
        throw new RuntimeException("写入次数超过3次而失败");
      }
      ++i;
    }
  }


  public boolean control(Map<String, Object> itemValues) {

    Iterator<Map.Entry<String, Object>> it = itemValues.entrySet().iterator();

    ItemValue p2[];
    p2 = new ItemValue[itemValues.size()];
    int i=0;
    while (it.hasNext()) {
      Map.Entry<String, Object> entry = it.next();
      log.info("即将写入值:"+entry.getKey() + ":" + entry.getValue());
      p2[i] = new ItemValue();
      p2[i].setItem_code(entry.getKey());
      p2[i].setItem_value(entry.getValue());
      i++;
    }

    return  this.control(p2);
  }



  public boolean control(ItemValue[] itemValues) {
    if (itemValues != null && itemValues.length != 0) {
      String this_items = JsonUtl.parseWithoutException(itemValues);
      boolean need_write = false;
      StringBuilder sb = new StringBuilder();
      ItemValue[] var5 = itemValues;
      int var6 = itemValues.length;

      for (int var7 = 0; var7 < var6; ++var7) {
        ItemValue itemValue = var5[var7];
        String code = itemValue.getItem_code();
        Object udw_value = this.getUdwValue(code);
        Object write_value = itemValue.getItem_value();
        sb.append(code);
        sb.append(":");
        sb.append(JsonUtl.parseWithoutException(udw_value));
        sb.append(";");
        if (!need_write && !UnifiedDataAppService.isEquals(udw_value, write_value)) {
          need_write = true;
        } else {
          log.info("下发信号点位{} 当前写入值:{} 与系统内存值:{} 相同，不再写入 ", code, write_value, udw_value );
        }
      }
      // need_write = true;

      if (need_write) {
        Date date = new Date();
        /*if (StringUtl.isEqual(this_items, this.last_items) && date.getTime() - this.sendTime.getTime() < (long) WcsConfig.opc_write_repeat_check) {
            log.trace("发送时间因为小于{}毫秒，而被无视", WcsConfig.opc_write_repeat_check);
            return false;
        }*/

        this.last_items = this_items;
        this.sendTime = date;
                /*  this.execute_log.setResource(this.getDevice().getCode(), this.getDevice().getName());
                this.execute_log.log("原始记录{}->变更为{}", new Object[]{sb, this_items});
                OpcServerService opcServerService = OpcServerFactory.getOpcServerService();*/

        OpcServerService opcServerService = SpringContextHolder.getBean(OpcServerServiceImpl.class);

        opcServerService.writeInteger(this.getOpcServer(), itemValues);
        UnifiedDataAccessor opcValueAccessor = this.getOpcValueAccessor();
        ItemValue[] var17 = itemValues;
        int var18 = itemValues.length;

        for (int var19 = 0; var19 < var18; ++var19) {
          ItemValue itemValue = var17[var19];
          String code = itemValue.getItem_code();
          Object value = itemValue.getItem_value();
          opcValueAccessor.setValue(code, value);
        }
      }

      return true;
    } else {
      throw new RuntimeException("下发 无内容");
    }
  }
}
