import React, {
  useImperativeHandle,
  useEffect,
  useRef,
  forwardRef,
} from 'react';
import {
  type ViewStyle,
  //   StyleSheet,
  SafeAreaView,
  //   NativeEventEmitter,
} from 'react-native';
import WebView from 'react-native-webview';
// import { JOdpModule } from 'react-native-ctp-odp';

const MapHtml = require('./JibestreamMap.html');
type LOG_LEVEL_TYPE = 'LOG' | 'DEBUG' | 'INFO' | 'WARN' | 'ERROR';

const handleLogMessage = (level: LOG_LEVEL_TYPE, message: string) => {
  switch (level) {
    case 'LOG':
      console.log('MESSAGE FROM WEBVIEW:', message);
      break;
    case 'DEBUG':
      console.debug('MESSAGE FROM WEBVIEW:', message);
      break;
    case 'INFO':
      console.info('MESSAGE FROM WEBVIEW:', message);
      break;
    case 'WARN':
      console.warn('MESSAGE FROM WEBVIEW:', message);
      break;
    case 'ERROR':
      console.error('MESSAGE FROM WEBVIEW:', message);
      break;
  }
};

const MapView = (
  props: {
    style?: ViewStyle;
    onMapMessage: MAP_EVENT_LISTENER_TYPE;
    onOdpEvent: ODP_EVENT_LISTENER_TYPE;
  },
  parentRef: React.Ref<unknown> | undefined
) => {
  const webviewRef = useRef(null);

  //   useEffect(() => {
  //     console.log('Initializing Event Emitter'); // "someValue"
  //     const eventEmitter = new NativeEventEmitter(JOdpModule);
  //     eventEmitter.addListener('onReady', (event) => {
  //       props.onOdpEvent.onReady?.(event as ODP_ON_READY_TYPE);
  //     });
  //     eventEmitter.addListener('onKeyValidation', (event) => {
  //       props.onOdpEvent.onKeyValidation?.(event as ODP_ON_KEY_VALIDATION_TYPE);
  //     });
  //     eventEmitter.addListener('onNavigationUpdate', (event) => {
  //       props.onOdpEvent.onNavigationUpdate?.(
  //         event as ODP_ON_NAVIGATION_UPDATE_TYPE
  //       );
  //     });
  //     eventEmitter.addListener('onFacilityUpdate', (event) => {
  //       props.onOdpEvent.onFacilityUpdate?.(event as ODP_ON_FACILITY_UPDATE_TYPE);
  //     });
  //     return () => {
  //       eventEmitter.removeAllListeners('onReady');
  //       eventEmitter.removeAllListeners('onKeyValidation');
  //       eventEmitter.removeAllListeners('onNavigationUpdate');
  //       eventEmitter.removeAllListeners('onFacilityUpdate');
  //     };
  //   }, []);

  useEffect(() => {}, []);

  const onWayfindToWaypoint = (waypointId: number) => {
    sendCommandToMap('WAYFIND_TO_WAYPOINT', waypointId);
  };

  const onWayfindBetweenWaypoints = (
    originId: number,
    destinationId: number
  ) => {
    sendCommandToMap('WAYFIND_BETWEEN_WAYPOINTS', { originId, destinationId });
  };

  const drawNavigationPath = (
    pathId: string,
    shouldFocus: boolean = true,
    style: JIBESTREAM_STYLE_TYPE = {
      stroke: '#ffc956',
      strokeWidth: 3,
    }
  ) => {
    sendCommandToMap('DRAW_NAVIGATION_PATH', { pathId, style, shouldFocus });
  };

  const onStyleShape = (
    unitId: number,
    style: JIBESTREAM_STYLE_TYPE = { fill: '#ABABAB' }
  ) => {
    sendCommandToMap('STYLE_SHAPE', { id: unitId, style });
  };

  const onStyleUnitsForDestination = (
    destination: JIBESTREAM_DESTINATION_TYPE,
    style: JIBESTREAM_STYLE_TYPE = { fill: '#ABABAB' }
  ) => {
    sendCommandToMap('STYLE_SHAPE', { destination, style });
  };

  useImperativeHandle(parentRef, () => {
    const listeners: MAP_VIEW_REFERENCE_TYPE = {
      setUserPosition: (lat: number, long: number) => {
        sendCommandToMap('UPDATE_USER_LOCATION', { lat, long });
      },
      wayfindToWaypoint: (waypointId: number) => {
        onWayfindToWaypoint(waypointId);
      },
      wayfindBetweenWaypoints: (originId: number, destinationId: number) => {
        onWayfindBetweenWaypoints(originId, destinationId);
      },
      drawNavigationPath: (
        pathId: string,
        shouldFocus?: boolean,
        style?: JIBESTREAM_STYLE_TYPE
      ) => {
        drawNavigationPath(pathId, shouldFocus, style);
      },
      styleUnitsForDestination: (
        destination: JIBESTREAM_DESTINATION_TYPE,
        style?: JIBESTREAM_STYLE_TYPE
      ) => {
        onStyleUnitsForDestination(destination, style);
      },
      styleShape: (unitId: number, style?: JIBESTREAM_STYLE_TYPE) => {
        onStyleShape(unitId, style);
      },
    };
    return listeners;
  });

  function onMessage(message: { nativeEvent: { data: string } }) {
    const obj: { command: COMMANDS_FROM_MAP; data: Object } = JSON.parse(
      message.nativeEvent.data
    );
    const command = obj.command;
    const data = obj.data;
    // props.onMapMessage(command, data);
    switch (command) {
      case 'DESTINATION_SELECTED':
        props.onMapMessage.onDestinationSelected?.(
          data as JIBESTREAM_DESTINATION_TYPE
        );
        break;
      case 'NAVIGATION_PATH_GENERATED':
        const obj = data as {
          pathId: string;
          instructions: INSTRUCTION_TYPE[];
          start: JIBESTREAM_WAYPOINT_TYPE;
          end: JIBESTREAM_WAYPOINT_TYPE;
          path: JIBESTREAM_PATH_TYPE[];
        };
        props.onMapMessage.onNavigationPathGenerated?.(
          obj.pathId,
          obj.instructions,
          obj.start,
          obj.end,
          obj.path
        );
        break;
      case 'USER_POSITION_UPDATED':
        props.onMapMessage.onUserPositionUpdated?.(data as number[]);
        break;
      case 'CONSOLE_LOG':
        const logObj = data as { level: LOG_LEVEL_TYPE; message: string };
        handleLogMessage(logObj.level, logObj.message);
        break;
      default:
        console.log('Unhandled command from map:', command, data);
        break;
    }
  }

  function sendCommandToMap(command: COMMANDS_TO_MAP, data: Object) {
    const clientResponseCode = `
    window.postMessage(${JSON.stringify({ command, data })}, "*");
    true;
  `;
    if (webviewRef.current)
      // @ts-ignore
      webviewRef.current.injectJavaScript(clientResponseCode);
  }

  return (
    <SafeAreaView style={{ flex: 1, width: '100%', height: '100%' }}>
      <WebView
        // injectedJavaScript={debugging}
        ref={webviewRef}
        scalesPageToFit={false}
        mixedContentMode="compatibility"
        onMessage={onMessage}
        source={MapHtml}
      />
    </SafeAreaView>
  );
};

export default forwardRef(MapView);
