/**
 * Version tags are loaded from the Github API. Since the Github API is rate-limited
 * we attempt to save and load the tags in sessionStorage when possible. Since its unlikely
 * that versions will change during a single session this should be safe.
 */

const TAGS_CACHE_KEY = '@react-dom-fixtures/tags';

/**
 * Its possible that users will be testing changes frequently
 * in a browser that does not support sessionStorage. If the API does
 * get rate limited this hardcoded fallback will be loaded instead.
 * This way users can still switch between ~some versions while testing.
 * If there's a specific version they need to test that is not here, they
 * can manually load it by editing the URL (`?version={whatever}`)
 */
const fallbackTags = [
  '15.4.2',
  '15.3.2',
  '15.2.1',
  '15.1.0',
  '15.0.2',
  '0.14.8',
  '0.13.0'
  ].map(version => ({
    name: `v${version}`
  }))

let canUseSessionStorage = true;

try {
  sessionStorage.setItem('foo', '')
} catch (err) {
  canUseSessionStorage = false;
}

/**
 * Attempts to load tags from sessionStorage. In cases where
 * sessionStorage is not available (Safari private browsing) or the
 * tags are cached a fetch request is made to the Github API.
 * 
 * Returns a promise so that the consuming module can always assume
 * the request is async, even if its loaded from sessionStorage.
 */
export default function getVersionTags() {
  return new Promise((resolve) => {
    let cachedTags;
    if (canUseSessionStorage) {
      cachedTags = sessionStorage.getItem(TAGS_CACHE_KEY);
    }
    if (cachedTags) {
      cachedTags = JSON.parse(cachedTags);
      resolve(cachedTags);
    } else {
      fetch('https://api.github.com/repos/facebook/react/tags', { mode: 'cors' })
        .then(res => res.json())
        .then(tags => {
          // A message property indicates an error was sent from the API
          if (tags.message) {
            return resolve(fallbackTags)
          }
          if (canUseSessionStorage) {
            sessionStorage.setItem(TAGS_CACHE_KEY, JSON.stringify(tags))
          }
          resolve(tags)
        })
        .catch(() => resolve(fallbackTags))
    }
  })
}