---
// fetch all commits for just this page's path
type Props = {
  path: string;
};
const { path } = Astro.props as Props;
const resolvedPath = `website/src/pages${path}.mdx`;
const url = `https://api.github.com/repos/tidalcycles/strudel/commits?path=${resolvedPath}`;
const commitsURL = `https://github.com/tidalcycles/strudel/commits/main/${resolvedPath}`;

type Commit = {
  author: {
    id: string;
    login: string;
  };
};

async function getCommits(url: string) {
  try {
    const token = import.meta.env.SNOWPACK_PUBLIC_GITHUB_TOKEN ?? 'hello';
    if (!token) {
      throw new Error('Cannot find "SNOWPACK_PUBLIC_GITHUB_TOKEN" used for escaping rate-limiting.');
    }

    const auth = `Basic ${Buffer.from(token, 'binary').toString('base64')}`;

    const res = await fetch(url, {
      method: 'GET',
      headers: {
        Authorization: auth,
        'User-Agent': 'astro-docs/1.0',
      },
    });

    const data = await res.json();

    if (!res.ok) {
      throw new Error(
        `Request to fetch commits failed. Reason: ${res.statusText}
       Message: ${data.message}`,
      );
    }

    return data as Commit[];
  } catch (e) {
    console.warn(`[error]  /src/components/AvatarList.astro 
    ${(e as any)?.message ?? e}`);
    return [] as Commit[];
  }
}

function removeDups(arr: Commit[]) {
  const map = new Map<string, Commit['author']>();
  for (let item of arr) {
    const author = item.author;
    // Deduplicate based on author.id
    //map.set(author.id, { login: author.login, id: author.id });
    author && map.set(author.id, { login: author.login, id: author.id });
  }

  return [...map.values()];
}

const data = await getCommits(url);
const unique = removeDups(data);
const recentContributors = unique.slice(0, 3); // only show avatars for the 3 most recent contributors
const additionalContributors = unique.length - recentContributors.length; // list the rest of them as # of extra contributors
---

<!-- Thanks to @5t3ph for https://smolcss.dev/#smol-avatar-list! -->
<div class="contributors px-4 mb-8">
  <ul class="avatar-list" style={`--avatar-count: ${recentContributors.length}`}>
    {
      recentContributors.map((item) => (
        <li>
          <a href={`https://github.com/${item.login}`}>
            <img
              alt={`Contributor ${item.login}`}
              title={`Contributor ${item.login}`}
              width="64"
              height="64"
              src={`https://avatars.githubusercontent.com/u/${item.id}`}
            />
          </a>
        </li>
      ))
    }
  </ul>
  {
    additionalContributors > 0 && (
      <span>
        <a href={commitsURL}>{`and ${additionalContributors} additional contributor${
          additionalContributors > 1 ? 's' : ''
        }.`}</a>
      </span>
    )
  }
  {unique.length === 0 && <a href={commitsURL}>Contributors</a>}
</div>

<style>
  .avatar-list {
    --avatar-size: 2.5rem;
    --avatar-count: 3;

    display: grid;
    list-style: none;
    /* Default to displaying most of the avatar to
  enable easier access on touch devices, ensuring
  the WCAG touch target size is met or exceeded */
    grid-template-columns: repeat(var(--avatar-count), max(44px, calc(var(--avatar-size) / 1.15)));
    /* `padding` matches added visual dimensions of
  the `box-shadow` to help create a more accurate
  computed component size */
    padding: 0.08em;
    font-size: var(--avatar-size);
  }

  @media (any-hover: hover) and (any-pointer: fine) {
    .avatar-list {
      /* We create 1 extra cell to enable the computed 
    width to match the final visual width */
      grid-template-columns: repeat(calc(var(--avatar-count) + 1), calc(var(--avatar-size) / 1.75));
    }
  }

  .avatar-list li {
    width: var(--avatar-size);
    height: var(--avatar-size);
  }

  .avatar-list li:hover ~ li a,
  .avatar-list li:focus-within ~ li a {
    transform: translateX(33%);
  }

  .avatar-list img,
  .avatar-list a {
    display: block;
    border-radius: 50%;
  }

  .avatar-list a {
    transition: transform 180ms ease-in-out;
  }

  .avatar-list img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    background-color: #fff;
    box-shadow: 0 0 0 0.05em #fff, 0 0 0 0.08em rgba(0, 0, 0, 0.15);
  }

  .avatar-list a:focus {
    outline: 2px solid transparent;
    /* Double-layer trick to work for dark and light backgrounds */
    box-shadow: 0 0 0 0.08em var(--theme-accent), 0 0 0 0.12em white;
  }

  .contributors {
    display: flex;
    align-items: center;
  }

  .contributors > * + * {
    margin-left: 0.75rem;
  }
</style>
