/*
   * (non-Javadoc)
   *
   * @see java.lang.Object#equals(java.lang.Object)
   */
  @Override
  public boolean equals(Object obj) {

    // quick checks first.

    // object handle identity
    if (this == obj) return true;

    // if it's null, it's not the same as anything
    // (and we can't compare its fields without a null pointer exception)
    if (obj == null) return false;

    // if it's some different class, well then something is bad.
    if (getClass() != obj.getClass()) return false;

    // ok so it's the same class. in that case, let's make a reference...
    PixelPusher other = (PixelPusher) obj;

    // if it differs by less than half a msec, it has no effect on our timing
    if (Math.abs(getUpdatePeriod() - other.getUpdatePeriod()) > 500) return false;

    // some fudging to cope with the fact that pushers don't know they have RGBOW
    if (this.hasRGBOW() & !other.hasRGBOW()) {
      if (getPixelsPerStrip() != other.getPixelsPerStrip() / 3) return false;
    }
    if (!this.hasRGBOW() & other.hasRGBOW()) {
      if (getPixelsPerStrip() / 3 != other.getPixelsPerStrip()) return false;
    }
    if (!(this.hasRGBOW() || other.hasRGBOW()))
      if (getPixelsPerStrip() != other.getPixelsPerStrip()) return false;
    if (getNumberOfStrips() != other.getNumberOfStrips()) return false;

    // handle the case where someone changed the config during library runtime
    if (this.artnet_channel != other.artnet_channel
        || this.artnet_universe != other.artnet_universe) return false;

    // if the port's been changed, we need to update
    if (this.my_port != other.my_port) return false;

    // we should update every time the power total changes significantly
    if (Math.abs(this.powerTotal - other.powerTotal) > 10000) return false;

    // handle the case where our power domain changed
    if (this.powerDomain != other.powerDomain) return false;

    // ditto for number of segments and pusherFlags
    if (this.segments != other.segments) return false;

    if (this.getPusherFlags() != other.getPusherFlags()) return false;

    // if all those other things are the same, then we call it good.
    return true;
  }
  public void copyHeader(PixelPusher device) {
    this.controllerOrdinal = device.controllerOrdinal;
    this.deltaSequence = device.deltaSequence;
    this.groupOrdinal = device.groupOrdinal;
    this.maxStripsPerPacket = device.maxStripsPerPacket;

    this.powerTotal = device.powerTotal;
    this.updatePeriod = device.updatePeriod;
    this.artnet_channel = device.artnet_channel;
    this.artnet_universe = device.artnet_universe;
    this.my_port = device.my_port;
    this.filename = device.filename;
    this.amRecording = device.amRecording;

    this.setPusherFlags(device.getPusherFlags());
    this.powerDomain = device.powerDomain;

    synchronized (stripLock) {
      // if the number of strips we have doesn't match,
      // we'll need to make a fresh set.
      if (this.stripsAttached != device.stripsAttached) {
        this.strips = null;
        this.stripsAttached = device.stripsAttached;
      }
      // likewise, if the length of each strip differs,
      // we will need to make a new set.
      if (this.pixelsPerStrip != device.pixelsPerStrip) {
        this.pixelsPerStrip = device.pixelsPerStrip;
        this.strips = null;
      }
      // and it's the same for segments
      if (this.segments != device.segments) {
        this.segments = device.segments;
        this.strips = null;
      }
      if (this.strips != null) for (Strip s : this.strips) s.setPusher(this);
    }
  }