import { useState, useEffect } from 'react';

const listeners = {};

function getSetAllValues(key, setValue) {
  if (!key) {
    // If no key just return the normal setValue function
    return setValue;
  }
  return value => listeners[key].forEach(fn => fn(value));
}

export default function usePersistedState(key, firstTimeDefault) {
  // If no key is passed in, act as a normal `useState`
  let defaultValue;
  let localStorageAvailable;

  try {
    localStorageAvailable = Boolean(window.localStorage);
  } catch (e) {
    localStorageAvailable = false;
  }
  if (key && localStorageAvailable) {
    let item = localStorage.getItem(key);

    if (item) {
      let parsedItem;
      try {
        parsedItem = JSON.parse(item);
      } catch (e) {}

      if (parsedItem !== undefined) {
        defaultValue = parsedItem;
      } else {
        defaultValue = item;
      }
    }
  }

  if (!defaultValue && defaultValue !== false) {
    defaultValue = firstTimeDefault;
  }

  const [value, setValue] = useState(defaultValue);

  if (key && !Array.isArray(listeners[key])) {
    listeners[key] = [];
  }

  useEffect(() => {
    if (key && localStorageAvailable) {
      localStorage.setItem(key, typeof value === 'object' ? JSON.stringify(value) : value);
    }
    if (key) {
      // add hook on mount
      listeners[key].push(setValue);
    }
    return () => {
      if (key) {
        // remove hook on unmount
        listeners[key] = listeners[key].filter(listener => listener !== setValue);
      }
    };
  }, [key, value, localStorageAvailable]);

  return [value, getSetAllValues(key, setValue)];
}
