content: package mods.eln.sixnode.thermalsensor;
  
  import mods.eln.Eln;
  import mods.eln.i18n.I18N;
  import mods.eln.item.ConfigCopyToolDescriptor;
  import mods.eln.item.IConfigurable;
  import mods.eln.misc.Direction;
  import mods.eln.misc.LRDU;
  import mods.eln.misc.Utils;
  import mods.eln.node.AutoAcceptInventoryProxy;
  import mods.eln.node.NodeBase;
  import mods.eln.node.six.SixNode;
  import mods.eln.node.six.SixNodeDescriptor;
  import mods.eln.node.six.SixNodeElement;
  import mods.eln.node.six.SixNodeElementInventory;
  import mods.eln.sim.ElectricalLoad;
  import mods.eln.sim.ThermalLoad;
  import mods.eln.sim.nbt.NbtElectricalGateOutputProcess;
  import mods.eln.sim.nbt.NbtElectricalLoad;
  import mods.eln.sim.nbt.NbtThermalLoad;
  import mods.eln.sixnode.currentcable.CurrentCableDescriptor;
  import mods.eln.sixnode.electricalcable.ElectricalCableDescriptor;
  import mods.eln.sixnode.electricaldatalogger.DataLogs;
  import mods.eln.sixnode.thermalcable.ThermalCableDescriptor;
  import net.minecraft.entity.player.EntityPlayer;
  import net.minecraft.inventory.Container;
  import net.minecraft.inventory.IInventory;
  import net.minecraft.item.ItemStack;
  import net.minecraft.nbt.NBTTagCompound;
  import org.jetbrains.annotations.NotNull;
  import org.jetbrains.annotations.Nullable;
  
  import java.io.DataInputStream;
  import java.io.DataOutputStream;
  import java.io.IOException;
  import java.util.HashMap;
  import java.util.Map;
  
  public class ThermalSensorElement extends SixNodeElement implements IConfigurable {
  
      public ThermalSensorDescriptor descriptor;
      public NbtThermalLoad thermalLoad = new NbtThermalLoad("thermalLoad");
      public NbtElectricalLoad outputGate = new NbtElectricalLoad("outputGate");
  
      public NbtElectricalGateOutputProcess outputGateProcess = new NbtElectricalGateOutputProcess("outputGateProcess", outputGate);
      public ThermalSensorProcess slowProcess = new ThermalSensorProcess(this);
  
      AutoAcceptInventoryProxy inventory;
  
      static final byte powerType = 0, temperatureType = 1;
      int typeOfSensor = temperatureType;
      float lowValue = 0, highValue = (float) Eln.SVU;
  
      public static final byte setTypeOfSensorId = 1;
      public static final byte setValueId = 2;
  
      public ThermalSensorElement(SixNode sixNode, Direction side, SixNodeDescriptor descriptor) {
          super(sixNode, side, descriptor);
          thermalLoadList.add(thermalLoad);
          electricalLoadList.add(outputGate);
          electricalComponentList.add(outputGateProcess);
          slowProcessList.add(slowProcess);
  
          this.descriptor = (ThermalSensorDescriptor) descriptor;
  
          if (this.descriptor.temperatureOnly) {
              inventory = (new AutoAcceptInventoryProxy(new SixNodeElementInventory(1, 64, this)))
                  .acceptIfEmpty(0, ThermalCableDescriptor.class, ElectricalCableDescriptor.class, CurrentCableDescriptor.class);
          } else {
              inventory = (new AutoAcceptInventoryProxy(new SixNodeElementInventory(1, 64, this)))
                  .acceptIfEmpty(0, ThermalCableDescriptor.class);
          }
      }
  
      public IInventory getInventory() {
          if (inventory != null)
              return inventory.getInventory();
          else
              return null;
      }
  
      public static boolean canBePlacedOnSide(Direction side, int type) {
          return true;
      }
  
      @Override
      public void readFromNBT(@NotNull NBTTagCompound nbt) {
          super.readFromNBT(nbt);
          byte value = nbt.getByte("front");
          front = LRDU.fromInt((value >> 0) & 0x3);
          typeOfSensor = nbt.getByte("typeOfSensor");
          lowValue = nbt.getFloat("lowValue");
          highValue = nbt.getFloat("highValue");
      }
  
      @Override
      public void writeToNBT(NBTTagCompound nbt) {
          super.writeToNBT(nbt);
          nbt.setByte("front", (byte) ((front.toInt() << 0)));
          nbt.setByte("typeOfSensor", (byte) typeOfSensor);
          nbt.setFloat("lowValue", lowValue);
          nbt.setFloat("highValue", highValue);
      }
  
      @Override
      public ElectricalLoad getElectricalLoad(LRDU lrdu, int mask) {
          if (front == lrdu) return outputGate;
  
          return null;
      }
  
      @Nullable
      @Override
      public ThermalLoad getThermalLoad(@NotNull LRDU lrdu, int mask) {
          if (!descriptor.temperatureOnly) {
              if (getInventory().getStackInSlot(ThermalSensorContainer.cableSlotId) != null) {
                  if (front.left() == lrdu) return thermalLoad;
                  if (front.right() == lrdu) return thermalLoad;
              }
          } else {
              if (front.inverse() == lrdu) return thermalLoad;
          }
          return null;
      }
  
      @Override
      public int getConnectionMask(LRDU lrdu) {
          if (!descriptor.temperatureOnly) {
              if (getInventory().getStackInSlot(ThermalSensorContainer.cableSlotId) != null) {
                  if (front.left() == lrdu) return NodeBase.maskThermal;
                  if (front.right() == lrdu) return NodeBase.maskThermal;
              }
              if (front == lrdu) return NodeBase.maskElectricalOutputGate;
          } else {
              if (isItemThermalCable()) {
                  if (front.inverse() == lrdu) return NodeBase.maskThermal;
              } else if (isItemElectricalCable()) {
                  if (front.inverse() == lrdu) return NodeBase.maskElectricalAll;
              }
              if (front == lrdu) return NodeBase.maskElectricalOutputGate;
          }
          return 0;
      }
  
      @Override
      public String multiMeterString() {
          return "";
      }
  
      @NotNull
      @Override
      public Map<String, String> getWaila() {
          Map<String, String> info = new HashMap<String, String>();
          info.put(I18N.tr("Output voltage"), Utils.plotVolt("", outputGate.getVoltage()));
          if (Eln.wailaEasyMode) {
              switch (typeOfSensor) {
                  case temperatureType:
                      info.put(I18N.tr("Measured temperature"), Utils.plotCelsius("", thermalLoad.getTemperature()));
                      break;
  
                  case powerType:
                      info.put(I18N.tr("Measured thermal power"), Utils.plotPower("", thermalLoad.getPower()));
                      break;
              }
          }
          return info;
      }
  
      @NotNull
      @Override
      public String thermoMeterString() {
          return Utils.plotCelsius("T :", thermalLoad.temperatureCelsius);
      }
  
      @Override
      public void networkSerialize(DataOutputStream stream) {
          super.networkSerialize(stream);
          try {
              stream.writeByte((front.toInt() << 4) + typeOfSensor);
              stream.writeFloat(lowValue);
              stream.writeFloat(highValue);
              Utils.serialiseItemStack(stream, getInventory().getStackInSlot(ThermalSensorContainer.cableSlotId));
          } catch (IOException e) {
              e.printStackTrace();
          }
      }
  
      @Override
      public void initialize() {
          Eln.instance.signalCableDescriptor.applyTo(outputGate);
          computeElectricalLoad();
      }
  
      @Override
      public void inventoryChanged() {
          sixNode.disconnect();
          computeElectricalLoad();
          sixNode.connect();
      }
  
      public void computeElectricalLoad() {
          ItemStack cable = getInventory().getStackInSlot(ThermalSensorContainer.cableSlotId);
  
          SixNodeDescriptor descriptor = Eln.sixNodeItem.getDescriptor(cable);
          if (descriptor == null) return;
          if (descriptor.getClass() == ThermalCableDescriptor.class) {
              ThermalCableDescriptor cableDescriptor = (ThermalCableDescriptor) Eln.sixNodeItem.getDescriptor(cable);
              cableDescriptor.setThermalLoad(thermalLoad);
              thermalLoad.setAsFast();
          } else if (descriptor.getClass() == ElectricalCableDescriptor.class) {
              ElectricalCableDescriptor cableDescriptor = (ElectricalCableDescriptor) Eln.sixNodeItem.getDescriptor(cable);
              cableDescriptor.applyTo(thermalLoad);
              thermalLoad.Rp = 1000000000.0;
              thermalLoad.setAsSlow();
          } else if (descriptor.getClass() == CurrentCableDescriptor.class) {
              CurrentCableDescriptor cableDescriptor = (CurrentCableDescriptor) Eln.sixNodeItem.getDescriptor(cable);
              cableDescriptor.applyTo(thermalLoad);
              thermalLoad.Rp = 1000000000.0;
              thermalLoad.setAsSlow();
          } else {
              thermalLoad.setHighImpedance();
          }
      }
  
      boolean isItemThermalCable() {
          SixNodeDescriptor descriptor = Eln.sixNodeItem.getDescriptor(getInventory().getStackInSlot(ThermalSensorContainer.cableSlotId));
          return descriptor != null && descriptor.getClass() == ThermalCableDescriptor.class;
      }
  
      boolean isItemElectricalCable() {
          SixNodeDescriptor descriptor = Eln.sixNodeItem.getDescriptor(getInventory().getStackInSlot(ThermalSensorContainer.cableSlotId));
          return descriptor != null && (descriptor.getClass() == ElectricalCableDescriptor.class || descriptor.getClass() == CurrentCableDescriptor.class);
      }
  
      @Override
      public boolean onBlockActivated(EntityPlayer entityPlayer, Direction side, float vx, float vy, float vz) {
          if (onBlockActivatedRotate(entityPlayer)) return true;
          ItemStack currentItemStack = entityPlayer.getCurrentEquippedItem();
  
          if (Eln.multiMeterElement.checkSameItemStack(currentItemStack)) {
              return false;
          }
          if (Eln.thermometerElement.checkSameItemStack(currentItemStack)) {
              return false;
          }
          if (Eln.allMeterElement.checkSameItemStack(currentItemStack)) {
              return false;
          }
          return inventory.take(currentItemStack, this, false, true);
      }
  
      @Override
      public void networkUnserialize(DataInputStream stream) {
          super.networkUnserialize(stream);
          try {
              switch (stream.readByte()) {
                  case setTypeOfSensorId:
                      typeOfSensor = stream.readByte();
                      needPublish();
                      break;
                  case setValueId:
                      lowValue = stream.readFloat();
                      highValue = stream.readFloat();
                      if (lowValue == highValue) highValue += 0.0001;
                      needPublish();
                      break;
              }
          } catch (IOException e) {
              e.printStackTrace();
          }
      }
  
      @Override
      public boolean hasGui() {
          return true;
      }
  
      @Nullable
      @Override
      public Container newContainer(@NotNull Direction side, @NotNull EntityPlayer player) {
          return new ThermalSensorContainer(player, inventory.getInventory(), descriptor.temperatureOnly);
      }
  
      @Override
      public void readConfigTool(NBTTagCompound compound, EntityPlayer invoker) {
          if(compound.hasKey("min"))
              lowValue = compound.getFloat("min");
          if(compound.hasKey("max"))
              highValue = compound.getFloat("max");
          if(compound.hasKey("unit")) {
              switch(compound.getByte("unit")) {
                  case DataLogs.powerType:
                      typeOfSensor = powerType;
                      break;
                  case DataLogs.celsiusType:
                      typeOfSensor = temperatureType;
                      break;
              }
          }
          ConfigCopyToolDescriptor.readCableType(compound, getInventory(), 0, invoker);
          reconnect();
      }
  
      @Override
      public void writeConfigTool(NBTTagCompound compound, EntityPlayer invoker) {
          compound.setFloat("min", lowValue);
          compound.setFloat("max", highValue);
          switch(typeOfSensor) {
              case powerType:
                  compound.setByte("unit", DataLogs.powerType);
                  break;
              case temperatureType:
                  compound.setByte("unit", DataLogs.celsiusType);
                  break;
          }
          ConfigCopyToolDescriptor.writeCableType(compound, getInventory().getStackInSlot(0));
      }
  }
  