import { clamp } from "../utilities.js";
/* @license
 * Copyright 2019 Google LLC. All Rights Reserved.
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
class ProgressTracker extends EventTarget {
  constructor() {
    super(...arguments);
    this.ongoingActivities = /* @__PURE__ */ new Set();
    this.totalProgress = 0;
  }
  /**
   * The total number of activities currently being tracked.
   */
  get ongoingActivityCount() {
    return this.ongoingActivities.size;
  }
  /**
   * Registers a new activity to be tracked by the progress tracker. The method
   * returns a special callback that should be invoked whenever new progress is
   * ready to be reported. The progress should be reported as a value between 0
   * and 1, where 0 would represent the beginning of the action and 1 would
   * represent its completion.
   *
   * There is no built-in notion of a time-out for ongoing activities, so once
   * an ongoing activity is begun, it is up to the consumer of this API to
   * update the progress until that activity is no longer ongoing.
   *
   * Progress is only allowed to move forward for any given activity. If a lower
   * progress is reported than the previously reported progress, it will be
   * ignored.
   */
  beginActivity() {
    const activity = { progress: 0, completed: false };
    this.ongoingActivities.add(activity);
    if (this.ongoingActivityCount === 1) {
      this.announceTotalProgress(activity, 0);
    }
    return (progress) => {
      let nextProgress;
      nextProgress = Math.max(clamp(progress, 0, 1), activity.progress);
      if (nextProgress !== activity.progress) {
        this.announceTotalProgress(activity, nextProgress);
      }
      return activity.progress;
    };
  }
  announceTotalProgress(updatedActivity, nextProgress) {
    let progressLeft = 0;
    let completedActivities = 0;
    if (nextProgress == 1)
      updatedActivity.completed = true;
    for (const activity of this.ongoingActivities) {
      const { progress } = activity;
      progressLeft += 1 - progress;
      if (activity.completed === true) {
        completedActivities++;
      }
    }
    const lastProgress = updatedActivity.progress;
    updatedActivity.progress = nextProgress;
    this.totalProgress += (nextProgress - lastProgress) * (1 - this.totalProgress) / progressLeft;
    const totalProgress = completedActivities === this.ongoingActivityCount ? 1 : this.totalProgress;
    this.dispatchEvent(new CustomEvent("progress", { detail: { totalProgress } }));
    if (completedActivities === this.ongoingActivityCount) {
      this.totalProgress = 0;
      this.ongoingActivities.clear();
    }
  }
}
export {
  ProgressTracker
};
//# sourceMappingURL=progress-tracker.js.map
