package info.guardianproject.keanuapp.ui.widgets;

import android.content.Context;
import android.media.AudioManager;
import android.media.MediaRecorder;
import android.net.Uri;
import android.util.Log;

import java.io.File;
import java.util.UUID;

import static info.guardianproject.keanu.core.KeanuConstants.LOG_TAG;

/**
 * Created by N-Pex on 2019-04-25.
 */
public class AudioRecorder {

    public interface AudioRecorderListener {
        void onAudioRecorded(Uri uri);
    }

    private Context context;
    private AudioRecorderListener listener;
    private boolean isAudioRecording = false;
    private MediaRecorder mediaRecorder;
    private File outputFilePath;
    private VisualizerView visualizerView;

    public AudioRecorder(Context context, AudioRecorderListener listener) {
        this.context = context;
        this.listener = listener;
    }

    public VisualizerView getVisualizerView() {
        return visualizerView;
    }

    public void setVisualizerView(VisualizerView visualizerView) {
        this.visualizerView = visualizerView;
    }

    public boolean isAudioRecording() {
        return isAudioRecording;
    }

    public void startAudioRecording() {
        AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        if (am.getMode() == AudioManager.MODE_NORMAL) {

            mediaRecorder = new MediaRecorder();

            String fileName = UUID.randomUUID().toString().substring(0, 8) + ".m4a";
            outputFilePath = new File(context.getFilesDir(), fileName);

            mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
            mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
            mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);

            //maybe we can modify these in the future, or allow people to tweak them
            mediaRecorder.setAudioChannels(1);
            mediaRecorder.setAudioEncodingBitRate(22050);
            mediaRecorder.setAudioSamplingRate(64000);

            mediaRecorder.setOutputFile(outputFilePath.getAbsolutePath());

            try {
                isAudioRecording = true;
                mediaRecorder.prepare();
                mediaRecorder.start();

                if (getVisualizerView() != null) {
                    startLevelListener();
                }
            } catch (Exception e) {
                Log.e(LOG_TAG, "couldn't start audio", e);
            }
        }
    }

    public int getAudioAmplitude() {
        return mediaRecorder.getMaxAmplitude();
    }

    private void startLevelListener() {
        getVisualizerView().post(levelListenerRunnable);
    }

    private Runnable levelListenerRunnable = new Runnable() {
        @Override
        public void run() {
            if (isAudioRecording) {
                getVisualizerView().updateVisualizerSingleValue(getAudioAmplitude());
                getVisualizerView().postDelayed(levelListenerRunnable, 100);
            }
        }
    };

    public void stopAudioRecording(boolean cancel) {
        if (mediaRecorder != null && outputFilePath != null && isAudioRecording) {

            try {

                mediaRecorder.stop();
                mediaRecorder.reset();
                mediaRecorder.release();

                if (!cancel) {
                    Uri uriAudio = Uri.fromFile(outputFilePath);
                    if (listener != null) {
                        listener.onAudioRecorded(uriAudio);
                    } else {
                        // No listener, abort
                        outputFilePath.delete();
                    }
                } else {
                    outputFilePath.delete();
                }
            } catch (IllegalStateException ise) {
                Log.w(LOG_TAG, "error stopping audio recording: " + ise);
            } catch (RuntimeException re) //stop can fail so we should catch this here
            {
                Log.w(LOG_TAG, "error stopping audio recording: " + re);
            }
            isAudioRecording = false;
        }
    }
}