type TileSnapshotSchedulerOptions = {
  publish: () => void;
  wait?: number;
};

export type TileSnapshotScheduler = {
  beginMove: () => void;
  endMove: () => void;
  markDirty: () => void;
  cancel: () => void;
};

export const createTileSnapshotScheduler = ({
  publish,
  wait = 100,
}: TileSnapshotSchedulerOptions): TileSnapshotScheduler => {
  let moving = false;
  let dirty = false;
  let timer: ReturnType<typeof setTimeout> | null = null;

  const clearTimer = () => {
    if (timer !== null) {
      clearTimeout(timer);
      timer = null;
    }
  };

  const schedule = () => {
    dirty = true;
    if (moving) return;
    clearTimer();
    timer = setTimeout(() => {
      timer = null;
      if (moving || !dirty) return;
      dirty = false;
      publish();
    }, wait);
  };

  return {
    beginMove: () => {
      moving = true;
      clearTimer();
    },
    endMove: () => {
      moving = false;
      schedule();
    },
    markDirty: schedule,
    cancel: () => {
      moving = false;
      dirty = false;
      clearTimer();
    },
  };
};
