class LocalSimMaxFrames extends LocalSim {
  queue;

  constructor(product, showDate) {
    super(product, showDate);
    this.queue = new HanisQueue(this.product.data.parameters.max_frames);

    product.data.images.forEach((img, index) => {
      img = img.replace(/[.](?=.*[.])/g, ":"); // replace all . with : except last (file extension)
      var imgObj = new HanisImage(
        img.split(".")[0],
        `${product.data.path}/${img}`,
        index
      );
      this.allImages.push(imgObj);
    });

    this.spreadOverlays(product);

    this.allImages.sort((a, b) => b.startTime - a.startTime);
    this.availableImages = this.allImages;
    this.init();
  }

  populateImageQueue(currentTime) {
    this.queue = new HanisQueue(this.product.data.parameters.max_frames);
    let startIndex = this.allImages.findIndex(
      (img) => img.startTime <= currentTime
    );
    this.availableImages = this.allImages.slice(
      0,
      startIndex + this.product.data.parameters.max_frames
    );
  }

  spreadOverlays(product) {
    if (!product.data.overlays) {
      return;
    }

    const imagesMapped = product.data.images.map((i) =>
      luxon.DateTime.fromISO(i.replace(/[.](?=.*[.])/g, ":").split(".")[0])
    );

    product.data.overlays.forEach((o) => {
      // static, one-to-one overlays don't need to be spread
      if (
        o.overlay_images.length === 1 ||
        o.overlay_images.length === product.data.images.length
      ) {
        return;
      }

      let spreadOverlay = [];

      const overlaysMapped = o.overlay_images.map((oi) =>
        luxon.DateTime.fromISO(
          oi.replace(/[.](?=.*[.])/g, ":").split(".")[0]
        )
      );

      let i = 0;
      let j = 0;

      while (i < product.data.images.length) {
        if (imagesMapped[i++] <= overlaysMapped[j]) {
          spreadOverlay.push(o.overlay_images[j]);
          continue;
        }
        if (
          j + 1 >= o.overlay_images.length ||
          imagesMapped[i] < overlaysMapped[j + 1]
        ) {
          spreadOverlay.push(o.overlay_images[j]);
        } else {
          spreadOverlay.push(o.overlay_images[j++]);
        }
      }

      o.overlay_images = spreadOverlay;
    });
  }

  onTick(currentTime) {
    if (!this.isOpen) return;

    var updatedTimes = false;

    // add new images
    var imagesToAdd = this.availableImages
      .filter((imgTime) => imgTime.startTime <= currentTime)
      .sort((a, b) => a.startTime - b.startTime);

    this.availableImages = this.availableImages.filter(
      (imgTime) => imgTime.startTime > currentTime
    );

    while (imagesToAdd.length > 0) {
      var img = imagesToAdd.shift();
      if (img !== undefined) {
        this.queue.enqueue(img);
        updatedTimes = true;
      }
    }

    // remove images in case time reset was called
    var imagesToRemove = this.queue.items.filter(
      (imgTime) => currentTime <= imgTime.startTime
    );

    this.queue.items = this.queue.items.filter(
      (imgTime) => currentTime > imgTime.startTime
    );

    if (imagesToRemove != 0) {
      this.availableImages = [...this.availableImages, ...imagesToRemove];
      updatedTimes = true;
    }

    if (updatedTimes) {
      this.htmlContent = parseHanis(
        this.product.name,
        this.queue.items
          .slice(0)
          .reverse()
          .map((displayedImg) => displayedImg.fullPath),
        this.queue.items
          .slice(0)
          .reverse()
          .map((displayedImg) => displayedImg.startTime),
        this.overlays?.map((overlay) => {
          if (
            overlay.overlay_images.length === 1 ||
            this.queue.items.length === 1
          ) {
            return overlay;
          }
          return {
            overlay_name: overlay.overlay_name,
            overlay_images: overlay.overlay_images.slice(
              this.queue.items[this.queue.items.length - 1].order,
              this.queue.items[this.queue.items.length - 1].order +
                this.queue.items.length
            ),
          };
        }),
        this.showDate,
        true
      );

      $("#main").html(this.htmlContent);
    }
  }
}
