import * as _ from 'lodash';
import { nanoid } from 'nanoid/non-secure';
import {
  NativeEventEmitter,
  NativeModules,
  Platform,
  processColor,
} from 'react-native';
import { BehaviorSubject, Subscription } from 'rxjs';
import type {
  MergeVideoParams,
  VideoMergeCallbackForOnProgress,
  VideoMergeEvent,
  VideoMergeRNRejectError,
} from './type';
export * from './type';

let debugMode: boolean = false;

export function setDebugMode(debug: boolean) {
  debugMode = debug;
}

const LINKING_ERROR =
  `The package 'react-native-video-merger' doesn't seem to be linked. Make sure: \n\n` +
  Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
  '- You rebuilt the app after installing the package\n' +
  '- You are not using Expo managed workflow\n';

const VideoMerger = NativeModules.VideoMerger
  ? NativeModules.VideoMerger
  : new Proxy(
      {},
      {
        get() {
          throw new Error(LINKING_ERROR);
        },
      }
    );
const eventEmitter = new NativeEventEmitter(VideoMerger);
export const eventSubscription = new BehaviorSubject<
  VideoMergeEvent | undefined
>(undefined);
eventEmitter.addListener(
  'RNVideoSDK:dataFromNative',
  (eventData: VideoMergeEvent) => {
    if (debugMode) {
      console.log('#[SDK] RNVideoSDK:dataFromNative', eventData);
    }
    eventSubscription.next(eventData);
  }
);
const __cache__ = {
  subscription: {} as { [key: string]: Subscription },
};

export function multiply(a: number, b: number): Promise<number> {
  return VideoMerger.multiply(a, b);
}

/**
 * 清理缓存目录
 * @returns undefined
 */
export async function cleanCacheDir() {
  return await VideoMerger.cleanCacheDir({});
}

/**
 * 开始合并视频
 * @param params MergeVideoParams
 * @returns
 */
export async function mergeVideos(
  _params: MergeVideoParams,
  onProgress?: VideoMergeCallbackForOnProgress
): Promise<VideoMergeEvent> {
  const params: Record<string, any> = _.cloneDeep(_params);
  if (params.backgroundColor) {
    params.backgroundColor = processColor(params.backgroundColor);
  }

  let eventDataCache: VideoMergeEvent
  return new Promise(async (resolve, reject) => {
    const subId = nanoid();
    const removeSubscription = () => {
      __cache__.subscription[subId]?.unsubscribe();
      delete __cache__.subscription[subId];
    };
    const sub: Subscription = eventSubscription.subscribe(
      (eventData: VideoMergeEvent | undefined) => {
        if (!eventData) {
          return;
        }
        const { errorCode, progress } = eventData;

        // check error
        const hasError = errorCode !== 0;
        if (hasError) {
          // removeSubscription();
          onProgress && onProgress(1);
          // reject(eventData);
          return;
        }

        // update progress
        onProgress && onProgress(progress);

        // check finished
        const isFinished = progress === 1;
        if (isFinished) {
          // removeSubscription();
          // resolve(eventData);
        }
      }
    );
    __cache__.subscription[subId] = sub;

    try {
      const res = await VideoMerger.mergeVideos(params);
      if (debugMode) {
        console.log('#[SDK] mergeVideos res', res);
      }
      if (!res.outputFilePath && eventDataCache?.outputFilePath) {
        res.outputFilePath = eventDataCache?.outputFilePath;
      }
      resolve(res);
    } catch (_error) {
      const error = _error as unknown as VideoMergeRNRejectError;
      console.log('###error', error.userInfo);
      reject(error.userInfo);
    }
    removeSubscription();
  });
}
