/**
 * Copyright (c) Nicolas Gallagher.
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @noflow
 */

import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment';
import findIndex from 'array-find-index';
import invariant from 'fbjs/lib/invariant';

// Android 4.4 browser
const isPrefixed =
  canUseDOM && !document.hasOwnProperty('hidden') && document.hasOwnProperty('webkitHidden');

const EVENT_TYPES = ['change', 'memoryWarning'];
const VISIBILITY_CHANGE_EVENT = isPrefixed ? 'webkitvisibilitychange' : 'visibilitychange';
const VISIBILITY_STATE_PROPERTY = isPrefixed ? 'webkitVisibilityState' : 'visibilityState';

const AppStates = {
  BACKGROUND: 'background',
  ACTIVE: 'active'
};

const listeners = [];

export default class AppState {
  static isAvailable = canUseDOM && document[VISIBILITY_STATE_PROPERTY];

  static get currentState() {
    if (!AppState.isAvailable) {
      return AppStates.ACTIVE;
    }

    switch (document[VISIBILITY_STATE_PROPERTY]) {
      case 'hidden':
      case 'prerender':
      case 'unloaded':
        return AppStates.BACKGROUND;
      default:
        return AppStates.ACTIVE;
    }
  }

  static addEventListener(type: string, handler: Function) {
    if (AppState.isAvailable) {
      invariant(
        EVENT_TYPES.indexOf(type) !== -1,
        'Trying to subscribe to unknown event: "%s"',
        type
      );
      if (type === 'change') {
        const callback = () => handler(AppState.currentState);
        listeners.push([handler, callback]);
        document.addEventListener(VISIBILITY_CHANGE_EVENT, callback, false);
      }
    }
  }

  static removeEventListener(type: string, handler: Function) {
    if (AppState.isAvailable) {
      invariant(
        EVENT_TYPES.indexOf(type) !== -1,
        'Trying to remove listener for unknown event: "%s"',
        type
      );
      if (type === 'change') {
        const listenerIndex = findIndex(listeners, pair => pair[0] === handler);
        invariant(
          listenerIndex !== -1,
          'Trying to remove AppState listener for unregistered handler'
        );
        const callback = listeners[listenerIndex][1];
        document.removeEventListener(VISIBILITY_CHANGE_EVENT, callback, false);
        listeners.splice(listenerIndex, 1);
      }
    }
  }
}