package com.prayagad.speech.utils;

import android.media.AudioRecord;
import android.os.Build;

import com.google.cloud.speech.v1beta1.StreamingRecognitionConfig;
import com.google.cloud.speech.v1beta1.StreamingRecognizeRequest;
import com.google.protobuf.ByteString;

import java.io.FileOutputStream;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicBoolean;

import io.grpc.stub.StreamObserver;

/**
 * Created by skishore on 5/1/17.
 */

public class AudioStreamerCallable implements Callable<Integer> {

    public static final int ERROR_CODE = 1;
    public static final int SUCCESS_CODE = 0;
    private final boolean saveToFile;
    private final StreamingRecognitionConfig config;
    private byte[] sData;
    private int bytesToRead;
    AudioRecord audioRecord;
    StreamObserver<StreamingRecognizeRequest> requestObserver = null;
    FileOutputStream os = null;

    private String location;
    //To Trigger a Stop Recording
    AtomicBoolean isRecording;


    public AudioStreamerCallable(AudioRecord recorder, int bytesToRead, StreamObserver<StreamingRecognizeRequest> requestObserver, StreamingRecognitionConfig config, AtomicBoolean isRecording, String location) {
        this.audioRecord = recorder;
        this.bytesToRead = bytesToRead;
        this.requestObserver = requestObserver;
        this.isRecording = isRecording;
        this.config = config;
        if (location == null) {
            saveToFile = false;
        } else {
            saveToFile = true;
            this.location = location;
        }
    }

    @Override
    public Integer call() throws Exception {
        System.out.println("Starting Recording and Streaming Data");
        System.out.println("Saving AudioFile at" + location);
        if (saveToFile) {
            os = new FileOutputStream(location);
        }
        StreamingRecognizeRequest initial =
                StreamingRecognizeRequest.newBuilder().setStreamingConfig(config).build();
        requestObserver.onNext(initial);
        try {
            while (isRecording.get()) {
                sData = new byte[bytesToRead];
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    audioRecord.read(sData, 0, bytesToRead, AudioRecord.READ_BLOCKING);
                } else {
                    audioRecord.read(sData, 0, bytesToRead);
                }

                StreamingRecognizeRequest request = StreamingRecognizeRequest.newBuilder()
                        .setAudioContent(ByteString.copyFrom(sData)).build();

                //System.out.println(request);
                if (saveToFile) {
                    os.write(sData, 0, bytesToRead);
                }
                requestObserver.onNext(request);
            }
            if (saveToFile) {
                os.close();
            }
            requestObserver.onCompleted();
        } catch (Exception e) {
            System.out.println(e.getMessage());
            return ERROR_CODE;
        }
        return SUCCESS_CODE;
    }
}
