// @ts-ignore
import React, {Component, ComponentProps, createElement} from 'react';
import {
    findNodeHandle,
    type HostComponent,
    type NativeMethods,
    requireNativeComponent,
    StyleSheet,
    View
} from "react-native";
import type {CameraViewNativeProps} from "./DynamsoftCameraViewNativeComponent";

/**
 * Transforms CameraViewNativeProps to a format compatible with the native CameraView component.
 * This ensures only supported properties are passed to the native layer.
 * @param props - The props for the {@link CameraView} component.
 * @returns The transformed native props.
 * @internal
 */
const transformToNativeCameraViewProps = (props: CameraViewNativeProps | undefined | null): CameraViewNativeProps => {
    return JSON.parse(JSON.stringify(
        {
            visibleLayerIds: props?.visibleLayerIds,
            scanRegionMaskVisible: props?.scanRegionMaskVisible,
            scanLaserVisible: props?.scanLaserVisible,
            torchButton: props?.torchButton,
            torchButtonVisible: props?.torchButtonVisible,
            cameraToggleButton: props?.cameraToggleButton,
            cameraToggleButtonVisible: props?.cameraToggleButtonVisible,
        }
    )) as CameraViewNativeProps
}
type RefType = React.Component<CameraViewNativeProps> & Readonly<NativeMethods>;

// @ts-ignore Check whether __turboModuleProxy exists, it may not
const isTurboModuleEnabled = global.__turboModuleProxy != null;

const ComponentName = 'DynamsoftCameraView';
const NativeCameraView: HostComponent<CameraViewNativeProps> = isTurboModuleEnabled?
    require("./DynamsoftCameraViewNativeComponent").default :
    requireNativeComponent(ComponentName)

/**
 * The CameraView class is a React Component that wraps the native CameraView, which is used to display the camera preview.
 * Users can add interactable UI elements on the view.
 * You can view {@link CameraViewNativeProps} to know what custom properties you can define.
 * Only available when CameraView is bound on CameraEnhancer by {@link CameraEnhancer.setCameraView} .
 * @prop {@link CameraViewNativeProps}
 * @see {@link CameraViewNativeProps}
 * @see {@link CameraEnhancer.setCameraView}
 */
export class CameraView extends Component<CameraViewNativeProps, any> {
    private readonly nativeCameraViewRef: React.RefObject<RefType | null> = React.createRef<RefType>();
    private readonly nativeProps = transformToNativeCameraViewProps(this.props)

    /** @internal */
    public get nativeCameraViewHandle(): number | null {
        return findNodeHandle(this.nativeCameraViewRef.current);
    }

    componentDidMount() {
      if(this.nativeProps.torchButton?.visible !== undefined) {
        console.warn("The `torchButton.visible` property of CameraView has been deprecated, please use the `torchButtonVisible` property of CameraView")
      }
    }

    componentDidUpdate(prevProps: CameraViewNativeProps) {
        let nativePreProps = transformToNativeCameraViewProps(prevProps)
        let nativeProps = transformToNativeCameraViewProps(this.props)
        if(nativePreProps !== nativeProps) {
            this.nativeCameraViewRef.current?.setNativeProps(nativeProps)
        }
    }

    public render(): React.ReactNode {
        return(
            <View style={[styles.blackBg, this.props?.style]}>
                <NativeCameraView
                    style={StyleSheet.absoluteFill}
                    ref={this.nativeCameraViewRef}
                    {...this.nativeProps}
                />

                {this.props?.children}
            </View>
        );
    }
}


const styles = StyleSheet.create({
    container: {
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center',
    },
    blackBg: {
        backgroundColor: 'black',
    },
});
