import type { Track } from "@applets/core/types.js";
import type { State } from "./types";
import { expose, transfer } from "@scripts/common.ts";

////////////////////////////////////////////
// STATE
////////////////////////////////////////////

const QUEUE_SIZE = 25;

const internal: { pool: Track[] } = {
  pool: [],
};

////////////////////////////////////////////
// ACTIONS
////////////////////////////////////////////
const actions = expose({
  add,
  pool,
  shift,
  unshift,
});

export type Actions = typeof actions;

// Actions

function add(state: State, items: Track[]): State {
  return transfer({ ...state, future: [...state.future, ...items] });
}

function pool(state: State, tracks: Track[]): State {
  internal.pool = tracks;

  // TODO: If the pool changes, only remove non-existing tracks
  //       instead of resetting the whole future queue.
  //
  //       What about past queue items?

  state = fill({ ...state, future: [] });

  // Automatically insert track if there isn't any
  if (!state.now) return shift(state);
  return transfer(state);
}

function shift(state: State): State {
  const now = state.future[0] || null;
  const future = state.future.slice(1);
  const past = state.now ? [...state.past, state.now] : state.past;
  const filled = fill({ past, now, future });

  return transfer(filled);
}

function unshift(state: State): State {
  if (state.past.length === 0) return state;

  const past = [...state.past];
  const [last] = past.splice(past.length - 1, 1);
  const now = last ?? null;
  const future = state.now ? [state.now, ...state.future] : state.future;

  return transfer({ past, now, future });
}

// 🛠️

// TODO: Shuffle, limit track amount, etc.
function fill(state: State): State {
  return state.future.length < QUEUE_SIZE
    ? add(
        state,
        internal.pool.slice(
          state.past.length,
          state.past.length + (QUEUE_SIZE - state.future.length),
        ),
      )
    : state;
}
