import React, { useState, useEffect } from "react";
import { Alert, ScrollView, StyleSheet, Text, TouchableHighlight, View } from "react-native";
import { useNavigation, Route } from "@react-navigation/native";
import { Conversation, Message } from "@/app/lib/conversation";
import MessageBubble from "@/components/ui/MessageBubble";
import { CachedTranslator, LanguageServer, language_matrix_entry } from "@/app/i18n/api";
import { Settings } from "@/app/lib/settings";
import { WHISPER_FILES } from "@/app/lib/whisper";
import { initWhisper, WhisperContext } from 'whisper.rn'
import { useAudioRecorder, AudioModule, RecordingPresets } from 'expo-audio';


const lasOptions = {
  sampleRate: 32000, // default is 44100 but 32000 is adequate for accurate voice recognition
  channels: 1, // 1 or 2, default 1
  bitsPerSample: 16, // 8 or 16, default 16
  audioSource: 6, // android only (see below)
  bufferSize: 4096, // default is 2048
};
// LiveAudioStream.init(lasOptions as any);

const ConversationThread = ({ route }: { route?: Route<"Conversation", { conversation: Conversation }> }) => {
  const navigation = useNavigation();

  if (!route) {
    return (<View><Text>Missing Params!</Text></View>)
  }

  /* 2. Get the param */
  const { conversation } = route?.params;

  const [messages, setMessages] = useState<Message[]>([]);
  const [guestSpeak, setGuestSpeak] = useState<string | undefined>();
  const [guestSpeakLoaded, setGuestSpeakLoaded] = useState<boolean>(false);
  const [whisperContext, setWhisperContext] = useState<WhisperContext | undefined>();
  const [cachedTranslator, setCachedTranslator] = useState<
    undefined | CachedTranslator
  >();

  const [languageLabels, setLanguageLabels] = useState<undefined | {
    hostNative: {
      host: string,
      guest: string,
    },
    guestNative: {
      host: string,
      guest: string,
    }
  }>()

  // recorder settings
  const audioRecorder = useAudioRecorder(RecordingPresets.HIGH_QUALITY);

  const record = async () => {
    await audioRecorder.prepareToRecordAsync();
    audioRecorder.record();
  };

  const stopRecording = async () => {
    // The recording will be available on `audioRecorder.uri`.
    await audioRecorder.stop();
  };

  useEffect(() => {
    (async function () {

      const languageServer = await LanguageServer.getDefault();
      try {
        const languages = await languageServer.fetchLanguages(5000);
        const cc = new CachedTranslator(
          "en",
          conversation.guest.language,
          languageServer,
        )
        console.log("Set cached translator from %s", languageServer.baseUrl)
        setCachedTranslator(cc);
      } catch (err) {
        console.error("Could not set translator from %s: %s", languageServer.baseUrl, err)
      }

      const settings = await Settings.getDefault();
      const whisperFile = WHISPER_FILES[await settings.getWhisperModel() || "en"];
      setWhisperContext(await initWhisper({
        filePath: whisperFile.targetPath,
      }));

      // recorder settings

      (async () => {
        const status = await AudioModule.requestRecordingPermissionsAsync();
        if (!status.granted) {
          Alert.alert('Permission to access microphone was denied');
        }
      })();
      setGuestSpeak(await cc.translate("Speak"));
      const hostLang1 = languages[conversation.host.language].name;
      const guestLang1 = languages[conversation.host.language].name;
      const hostLang2 = await cc.translate(languages[conversation.host.language].name);
      const guestLang2 = await cc.translate(languages[conversation.host.language].name);
      setLanguageLabels({
        hostNative: {
          host: hostLang1,
          guest: guestLang1,
        },
        guestNative: {
          host: hostLang2,
          guest: guestLang2,
        }
      })
    })();

    const updateMessages = (c: Conversation) => {
      setMessages([...c]);
    };

    if (!conversation) {
      console.warn("Conversation is null or undefined.")
    }

    conversation.on("add_message", updateMessages);
    conversation.on("translation_done", updateMessages);

    // return () => {
    //   conversation.on("add_message", undefined);
    //   conversation.on("translation_done", undefined);
    // };
  }, [conversation, guestSpeak]);

  const renderMessages = () =>
    messages.map((message, index) => (
      <MessageBubble key={index} message={message} />
    ));

  return cachedTranslator ? (
    <View style={{ flex: 1, flexDirection: "column" }}>
      {languageLabels && (<View style={styles.languageLabels}>
        <Text style={styles.nativeHostLabel}>{languageLabels.hostNative.host} / {languageLabels.hostNative.guest}</Text>
        <Text style={styles.nativeGuestLabel}>{languageLabels.guestNative.host} / {languageLabels.guestNative.guest}</Text>
      </View>)
      }
      <ScrollView
        style={{
          borderColor: "black",
          borderWidth: 1,
          borderStyle: "solid",
          height: "90%",
        }}
      >
        {renderMessages()}
      </ScrollView>
      <View style={{ alignSelf: "center", flexDirection: "row" }}>
        <TouchableHighlight
          style={{ backgroundColor: "blue", padding: 3, borderRadius: 5 }}
        >
          <Text style={{ color: "white", fontSize: 30 }}>Speak</Text>
        </TouchableHighlight>
        <TouchableHighlight
          style={{ backgroundColor: "gray", padding: 3, borderRadius: 5 }}
          onPress={navigation.goBack}
        >
          <Text style={{ color: "white", fontSize: 30 }}>Go Back</Text>
        </TouchableHighlight>
        <TouchableHighlight
          style={{ backgroundColor: "blue", padding: 3, borderRadius: 5 }}
        >
          <Text style={{ color: "white", fontSize: 30 }}>
            {guestSpeak ? guestSpeak : "Speak"}
          </Text>
        </TouchableHighlight>
      </View>
    </View>
  ) : (
    <View>
      <Text>Loading...</Text>
    </View>
  );
};

const styles = StyleSheet.create({
  languageLabels: {

  },
  nativeHostLabel: {

  },
  nativeGuestLabel: {

  },
})

export default ConversationThread;
