public long getAvailWentBadTime() {
    PEPeerManager pm = download_manager.getPeerManager();

    if (pm != null) {

      long bad_time = pm.getAvailWentBadTime();

      if (bad_time > 0) {

        // valid last bad time

        return (bad_time);
      }

      if (pm.getMinAvailability() >= 1.0) {

        // we can believe the fact that it isn't bad (we want to ignore 0 results from
        // downloads that never get to a 1.0 availbility)

        return (0);
      }
    }

    DownloadManagerState state = download_manager.getDownloadState();

    return (state.getLongAttribute(DownloadManagerState.AT_AVAIL_BAD_TIME));
  }
  public void resetTotalBytesSentReceived(long new_sent, long new_received) {
    boolean running = download_manager.getPeerManager() != null;

    if (running) {

      download_manager.stopIt(DownloadManager.STATE_STOPPED, false, false);
    }

    if (new_sent >= 0) {

      saved_data_bytes_uploaded = new_sent;
      session_start_data_bytes_uploaded = new_sent;
      saved_protocol_bytes_uploaded = 0;
    }

    if (new_received >= 0) {

      saved_data_bytes_downloaded = new_received;
      session_start_data_bytes_downloaded = new_received;
      saved_protocol_bytes_downloaded = 0;
    }

    saved_discarded = 0;
    saved_hashfails = 0;

    if (running) {

      download_manager.setStateWaiting();
    }
  }
  public long getTotalDataBytesReceived() {
    PEPeerManager pm = download_manager.getPeerManager();

    if (pm != null) {
      return saved_data_bytes_downloaded + pm.getStats().getTotalDataBytesReceived();
    }
    return (saved_data_bytes_downloaded);
  }
  public String getElapsedTime() {
    PEPeerManager pm = download_manager.getPeerManager();

    if (pm != null) {
      return pm.getElapsedTime();
    }

    return "";
  }
  public long getHashFailBytes() {
    PEPeerManager pm = download_manager.getPeerManager();

    if (pm != null) {

      return saved_hashfails + pm.getStats().getTotalHashFailBytes();
    }

    return (saved_hashfails);
  }
  public long getDiscarded() {
    PEPeerManager pm = download_manager.getPeerManager();

    if (pm != null) {

      return saved_discarded + pm.getStats().getTotalDiscarded();
    }

    return (saved_discarded);
  }
  public long getTotalProtocolBytesSent() {
    PEPeerManager pm = download_manager.getPeerManager();

    if (pm != null) {

      return saved_protocol_bytes_uploaded + pm.getStats().getTotalProtocolBytesSent();
    }

    return (saved_protocol_bytes_uploaded);
  }
  private long getTimeStartedSeeding(boolean mono) {
    PEPeerManager pm = download_manager.getPeerManager();

    if (pm != null) {

      return (pm.getTimeStartedSeeding(mono));
    }

    return -1;
  }
  public long getSmoothedETA() {
    PEPeerManager pm = download_manager.getPeerManager();

    if (pm != null) {

      return pm.getETA(true);
    }

    return -1; // return exactly -1 if ETA is unknown
  }
  public long getSmoothedDataSendRate() {
    PEPeerManager pm = download_manager.getPeerManager();

    if (pm != null) {

      return (pm.getStats().getSmoothedDataSendRate());
    }

    return (0);
  }
  public long getTotalAverage() {
    PEPeerManager pm = download_manager.getPeerManager();

    if (pm != null) {

      return pm.getStats().getTotalAverage();
    }

    return (0);
  }
  public long getDataReceiveRate() {
    PEPeerManager pm = download_manager.getPeerManager();

    if (pm != null) {

      return pm.getStats().getDataReceiveRate();
    }

    return 0;
  }
  public long getProtocolSendRate() {
    PEPeerManager pm = download_manager.getPeerManager();

    if (pm != null) {

      return pm.getStats().getProtocolSendRate();
    }

    return 0;
  }
  public long getBytesUnavailable() {
    PEPeerManager pm = download_manager.getPeerManager();

    if (pm == null) {

      return (-1);
    }

    return (pm.getBytesUnavailable());
  }
  public float getAvailability() {
    PEPeerManager pm = download_manager.getPeerManager();

    if (pm == null) {

      return (-1);
    }

    return (pm.getMinAvailability());
  }
  public long getPeakDataSendRate() {
    PEPeerManager pm = download_manager.getPeerManager();

    long result = saved_peak_send_rate;

    if (pm != null) {

      result = Math.max(result, pm.getStats().getPeakDataSendRate());
    }

    return (result);
  }
  public void setShareRatio(int ratio) {
    if (ratio < 0) {
      ratio = 0;
    }

    if (ratio > 1000000) {
      ratio = 1000000;
    }

    DiskManagerFileInfo[] files = download_manager.getDiskManagerFileInfoSet().getFiles();

    long total_size = 0;

    for (DiskManagerFileInfo file : files) {

      if (!file.isSkipped()) {

        total_size += file.getLength();
      }
    }

    if (total_size == 0) {

      // can't do much if they have no files selected (which would be stupid anyway)

      return;
    }

    saved_hashfails = 0;
    saved_discarded = 0;
    saved_data_bytes_downloaded = 0;
    saved_data_bytes_uploaded = 0;

    long downloaded = getTotalGoodDataBytesReceived();
    long uploaded = getTotalDataBytesSent();

    // manipulate by updating downloaded to be one full copy and then uploaded as required

    long target_downloaded = total_size;
    long target_uploaded = (ratio * total_size) / 1000;

    saved_data_bytes_downloaded = target_downloaded - downloaded;
    saved_data_bytes_uploaded = target_uploaded - uploaded;

    if (download_manager.getPeerManager() == null) {

      saveSessionTotals();
    }
  }
  public int getTimeSinceLastDataSentInSeconds() {
    PEPeerManager pm = download_manager.getPeerManager();

    int res = saved_SecondsSinceUpload;

    if (pm != null) {

      int current = pm.getStats().getTimeSinceLastDataSentInSeconds();

      if (current >= 0) {

        // activity this session, use this value

        res = current;

      } else {

        // no activity this session. If ever has been activity add in session
        // time

        if (res >= 0) {

          long now = SystemTime.getCurrentTime();

          long elapsed = now - pm.getTimeStarted(false);

          if (elapsed < 0) {

            elapsed = 0;
          }

          res += elapsed / 1000;
        }
      }
    }

    return (res);
  }
  protected void timerTick(int tick_count) {
    if (tick_count % 15 == 0) {

      if (last_sr_progress == -1) {

        long temp =
            download_manager
                .getDownloadState()
                .getLongAttribute(DownloadManagerState.AT_SHARE_RATIO_PROGRESS);

        last_sr_progress = (int) temp;
      }

      if (share_ratio_progress_interval <= 0) {

        // reset

        if (last_sr_progress != 0) {

          last_sr_progress = 0;

          download_manager
              .getDownloadState()
              .setLongAttribute(DownloadManagerState.AT_SHARE_RATIO_PROGRESS, 0);
        }
      } else {

        int current_sr = getShareRatio();

        current_sr = (current_sr / share_ratio_progress_interval) * share_ratio_progress_interval;

        if (current_sr != last_sr_progress) {

          last_sr_progress = current_sr;

          long data = ((SystemTime.getCurrentTime() / 1000) << 32) + last_sr_progress;

          download_manager
              .getDownloadState()
              .setLongAttribute(DownloadManagerState.AT_SHARE_RATIO_PROGRESS, data);
        }
      }
    }

    if (!history_retention_required) {

      return;
    }

    PEPeerManager pm = download_manager.getPeerManager();

    if (pm == null) {

      return;
    }

    PEPeerManagerStats stats = pm.getStats();

    long send_rate = stats.getDataSendRate() + stats.getProtocolSendRate();
    long receive_rate = stats.getDataReceiveRate() + stats.getProtocolReceiveRate();
    long peer_swarm_average = getTotalAveragePerPeer();

    long entry =
        ((((send_rate - 1 + HISTORY_DIV / 2) / HISTORY_DIV) << 42) & 0x7ffffc0000000000L)
            | ((((receive_rate - 1 + HISTORY_DIV / 2) / HISTORY_DIV) << 21) & 0x000003ffffe00000L)
            | ((((peer_swarm_average - 1 + HISTORY_DIV / 2) / HISTORY_DIV)) & 0x00000000001fffffL);

    synchronized (this) {
      if (history != null) {

        history[history_pos++] = entry;

        if (history_pos == HISTORY_MAX_SECS) {

          history_pos = 0;
          history_wrapped = true;
        }
      }
    }
  }