/**
 * 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.
 *
 * @format
 * @flow
 */

'use strict';

import EventEmitter from '../vendor/emitter/EventEmitter';
import NativeEventEmitter from '../EventEmitter/NativeEventEmitter';
import NativeAppearance, {
  type AppearancePreferences,
  type ColorSchemeName,
} from './NativeAppearance';
import invariant from 'invariant';
import {isAsyncDebugging} from './DebugEnvironment';

type AppearanceListener = (preferences: AppearancePreferences) => void;
const eventEmitter = new EventEmitter();

if (NativeAppearance) {
  const nativeEventEmitter = new NativeEventEmitter(NativeAppearance);
  nativeEventEmitter.addListener(
    'appearanceChanged',
    (newAppearance: AppearancePreferences) => {
      const {colorScheme} = newAppearance;
      invariant(
        colorScheme === 'dark' ||
          colorScheme === 'light' ||
          colorScheme == null,
        "Unrecognized color scheme. Did you mean 'dark' or 'light'?",
      );
      eventEmitter.emit('change', {colorScheme});
    },
  );
}

module.exports = {
  /**
   * Note: Although color scheme is available immediately, it may change at any
   * time. Any rendering logic or styles that depend on this should try to call
   * this function on every render, rather than caching the value (for example,
   * using inline styles rather than setting a value in a `StyleSheet`).
   *
   * Example: `const colorScheme = Appearance.getColorScheme();`
   *
   * @returns {?ColorSchemeName} Value for the color scheme preference.
   */
  getColorScheme(): ?ColorSchemeName {
    if (__DEV__) {
      if (isAsyncDebugging) {
        // Hard code light theme when using the async debugger as
        // sync calls aren't supported
        return 'light';
      }
    }

    // TODO: (hramos) T52919652 Use ?ColorSchemeName once codegen supports union
    const nativeColorScheme: ?string =
      NativeAppearance == null
        ? null
        : NativeAppearance.getColorScheme() || null;
    invariant(
      nativeColorScheme === 'dark' ||
        nativeColorScheme === 'light' ||
        nativeColorScheme == null,
      "Unrecognized color scheme. Did you mean 'dark' or 'light'?",
    );
    return nativeColorScheme;
  },
  /**
   * Add an event handler that is fired when appearance preferences change.
   */
  addChangeListener(listener: AppearanceListener): void {
    eventEmitter.addListener('change', listener);
  },
  /**
   * Remove an event handler.
   */
  removeChangeListener(listener: AppearanceListener): void {
    eventEmitter.removeListener('change', listener);
  },
};

@@ -1115,460 +1115,112 @@
     
-eventEmitter.emit('change', %7BcolorScheme%7D);%0A    %7D,%0A  );%0A%7D%0A%0Amodule.exports = %7B%0A  /**%0A   * Note: Although color scheme is available immediately, it may change at any%0A   * time. Any rendering logic or styles that depend on this should try to call%0A   * this function on every render, rather than caching the value (for example,%0A   * using inline styles rather than setting a value in a %60StyleSheet%60).%0A   *%0A   * Example: %60const colorScheme = Appearance.getC
+// Update cached value%0A      preferences.colorScheme = colorScheme;%0A      eventEmitter.emit('change', %7Bc
 olor
@@ -1229,101 +1229,46 @@
 heme
-(
+%7D
 );
-%60
 %0A   
-*%0A   * @returns %7B?ColorSchemeName%7D Value for the color scheme preference.%0A   */%0A  get
+ %7D,%0A  );%0A%7D%0A%0Afunction getInitial
 Colo
@@ -1297,18 +1297,16 @@
 eName %7B%0A
-  
   if (__
@@ -1318,18 +1318,16 @@
 ) %7B%0A    
- 
- 
 if (isAs
@@ -1342,18 +1342,16 @@
 ging) %7B%0A
-  
       //
@@ -1412,18 +1412,16 @@
 s%0A      
-  
 // sync 
@@ -1449,18 +1449,16 @@
 d%0A      
- 
- 
 return '
@@ -1473,21 +1473,15 @@
     
-  %7D%0A  
+%7D%0A
   %7D%0A%0A
-  
   //
@@ -1555,18 +1555,16 @@
 s union%0A
-  
   const 
@@ -1596,18 +1596,16 @@
 g =%0A    
-  
 NativeAp
@@ -1624,31 +1624,15 @@
 null
-%0A        ? null%0A       
+ ? null
  : N
@@ -1673,18 +1673,16 @@
 %7C null;%0A
-  
   invari
@@ -1682,26 +1682,24 @@
  invariant(%0A
-  
     nativeCo
@@ -1720,34 +1720,32 @@
 'dark' %7C%7C%0A      
- 
- 
 nativeColorSchem
@@ -1763,26 +1763,24 @@
 t' %7C%7C%0A      
-  
 nativeColorS
@@ -1790,26 +1790,24 @@
 me == null,%0A
-  
     %22Unrecog
@@ -1866,46 +1866,860 @@
 ,%0A  
-  );%0A    return nativeColorScheme;%0A  %7D
+);%0A  return nativeColorScheme;%0A%7D%0A%0Afunction getColorScheme(): ?ColorSchemeName %7B%0A  if (!preferences.colorScheme) %7B%0A    const initialColorScheme = getInitialColorScheme();%0A    preferences.colorScheme = initialColorScheme;%0A    return preferences.colorScheme;%0A  %7D%0A%0A  return preferences.colorScheme;%0A%7D%0A%0Aconst preferences = %7B%0A  colorScheme: null,%0A%7D;%0A%0Amodule.exports = %7B%0A  /**%0A   * Note: Although color scheme is available immediately, it may change at any%0A   * time. Any rendering logic or styles that depend on this should try to call%0A   * this function on every render, rather than caching the value (for example,%0A   * using inline styles rather than setting a value in a %60StyleSheet%60).%0A   *%0A   * Example: %60const colorScheme = Appearance.getColorScheme();%60%0A   *%0A   * @returns %7B?ColorSchemeName%7D Value for the color scheme preference.%0A   */%0A  getColorScheme
 ,%0A  

Use listener whenever possible in order to respect userInterfaceStyle of RCTRootView - getColorScheme does not do this by default