(function () {
  const prefix = 'lan-play:release:v1:';

  function folder(path) {
    const index = path.lastIndexOf('/');
    return index < 0 ? '' : path.slice(0, index);
  }

  function key(path) {
    return `${prefix}${folder(path)}`;
  }

  function load(path) {
    try { return JSON.parse(localStorage.getItem(key(path))) || {}; }
    catch (_) { return {}; }
  }

  function store(path, value) {
    try { localStorage.setItem(key(path), JSON.stringify(value)); } catch (_) {}
  }

  function label(track) {
    const labels = track && track.labels || [];
    const selected = labels.find((item) => item.text) || labels[0];
    return selected && selected.text || track && track.label || '';
  }

  function descriptor(track, ordinal) {
    if (!track) return { off: true };
    return {
      off: false,
      lang: track.lang || track.language || '',
      label: label(track),
      roles: (track.roles || []).map((role) => role.value || role).filter(Boolean).sort(),
      ordinal
    };
  }

  function remember(path, type, track, ordinal) {
    const profile = load(path);
    profile[type] = descriptor(track, ordinal);
    store(path, profile);
  }

  function find(path, type, tracks) {
    const wanted = load(path)[type];
    if (!wanted) return undefined;
    if (wanted.off) return null;
    const described = tracks.map((track, ordinal) => ({ track, ordinal, value: descriptor(track, ordinal) }));
    let matches = described.filter((item) => wanted.lang && item.value.lang === wanted.lang);
    if (wanted.label) {
      const labeled = matches.filter((item) => item.value.label === wanted.label);
      if (labeled.length) matches = labeled;
    }
    if (!matches.length && wanted.label) {
      matches = described.filter((item) => item.value.label === wanted.label);
    }
    if (!matches.length && !wanted.lang && !wanted.label) matches = described;
    return (matches.find((item) => item.ordinal === wanted.ordinal) || matches[0] || {}).track;
  }

  window.LanPlayPreferences = { folder, load, remember, find };
})();
