import React, {useEffect, useRef, useState} from "react";

//strings
import strings from "../constants/localization";

//actions

//components
import {Button} from "../../../Talk-ui-kit/src/button";
import {Text} from "../../../Talk-ui-kit/src/typography";
import Divider from "../../../Talk-ui-kit/src/divider";
import Gap from "../../../Talk-ui-kit/src/gap";
import Container from "../../../Talk-ui-kit/src/container";

//styling
import style from "../../styles/app/AsideHeadChatSettingsCallTest.scss";

//statics
function colorPids(vol) {
  const allPids = [...document.getElementsByClassName(style.AsideHeadChatSettingsCallTest__Pid)];
  const numberOfPidsToColor = Math.round(vol / 10);
  const pidsToColor = allPids.slice(0, numberOfPidsToColor);
  for (const pid of allPids) {
    pid.style.backgroundColor = style.colorGray;
  }
  for (const pid in pidsToColor) {
    const colorIndex = {
      0: style.colorGreenLight,
      1: style.colorGreen,
      2: style.colorGreenDark,
      3: style.colorYellowLight,
      4: style.colorYellow,
      5: style.colorYellowDark,
      6: style.colorRedLight,
      7: style.colorRed,
      8: style.colorRedDark,
      9: style.colorRedDark
    }
    pidsToColor[pid].style.backgroundColor = colorIndex[pid];
  }
}

function ErrorGenerator({isVideo, err, onRetry}) {
  const string = strings.gettingStreamError(isVideo, err);
  return <Container centerTextAlign>
    <Text whiteSpace="preWrap" size="xs" bold color="red">{string}</Text>
    {(err.name !== "NotAllowedError" && onRetry) &&
    <Button text onClick={onRetry}>{strings.retry}</Button>
    }
  </Container>;
}

function closeStream(stream) {
  stream.getTracks().forEach(function(track) {
      track.stop();
  });
  return true;
}

export default function ({}) {
  const [micError, setMicError] = useState(null);
  const [cameraError, setCameraError] = useState(null);
  let videoStream, audioStream, audioContext;
  const videoRef = useRef();

  useEffect(() => {
    return ()=> {
      videoStream && closeStream(videoStream)
      audioStream && closeStream(audioStream) && audioContext.close();
    }
  },[])
  const getCam = () => navigator.mediaDevices.getUserMedia({
    video: {
      facingMode: "user"
    }
  }).then(function (mediaStream) {
    videoStream = mediaStream;
    if (cameraError) {
      setCameraError(null);
    }
    videoRef.current.srcObject = mediaStream;
  }).catch(function (err) {
    if (!cameraError) {
      setCameraError(err);
    }
  });

  const getMic = () => navigator.mediaDevices.getUserMedia({
    audio: true,
  })
    .then(function (stream) {
      audioStream = stream;
      audioContext = new AudioContext();
      const analyser = audioContext.createAnalyser();
      const microphone = audioContext.createMediaStreamSource(stream);
      const scriptProcessor = audioContext.createScriptProcessor(2048, 1, 1);
      if (micError) {
        setMicError(null);
      }
      analyser.smoothingTimeConstant = 0.8;
      analyser.fftSize = 1024;

      microphone.connect(analyser);
      analyser.connect(scriptProcessor);
      scriptProcessor.connect(audioContext.destination);
      scriptProcessor.onaudioprocess = function () {
        const array = new Uint8Array(analyser.frequencyBinCount);
        analyser.getByteFrequencyData(array);
        const arraySum = array.reduce((a, value) => a + value, 0);
        const average = arraySum / array.length;
        colorPids(average);
      };
    })
    .catch(function (err) {
      if (!micError) {
        setMicError(err);
      }
    });

  getMic();
  getCam();

  return <Gap x={10} y={10} block>

    <Text bold color="gray" dark>{strings.mic}</Text>
    <Gap y={10}/>

    <Container className={style.AsideHeadChatSettingsCallTest__PidContainer} display="flex" justifyContent="center">
      {micError ?
        <ErrorGenerator isVideo={false} err={micError} onRetry={getMic}/>
        :
        [...Array(10)].map((e, i) => <Container className={style.AsideHeadChatSettingsCallTest__Pid}/>)
      }
    </Container>
    <Gap y={30} block>
      <Divider thick={1} color="gray"/>
    </Gap>
    <Text bold color="gray" dark>{strings.cam}</Text>
    <Gap y={10}/>
    <Container display="flex" justifyContent="center">
      {cameraError ?
        <ErrorGenerator isVideo err={cameraError} onRetry={getCam}/>
        :
        <video className={style.AsideHeadChatSettingsCallTest__Video} autoPlay muted playsInline ref={videoRef}/>
      }

    </Container>

  </Gap>;
}