package com.example.kingway.ptt;

import android.media.AudioAttributes;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import timber.log.Timber;

import java.util.ArrayList;
import java.util.List;

public class pttNative {
    private static String TAG = "pttNative";
    static {
        try {
            System.loadLibrary("ptt");
            Timber.tag(TAG).d("Native library 'ptt' loaded successfully");
        } catch (Throwable e) {
            Timber.tag(TAG).e(e, "Failed to load ptt library");
        }
    }

    public static char Char2ASCII(char c)
    {
        return (char) (c <= 9 ? (c+0x30) : (c+0x37));
    }

    public static char Ascii2Char(char nib_h, char nib_l)
    {
        nib_h = (nib_h <= '9')?((char)(nib_h-0x30)):(((nib_h<='F')?((char)(nib_h-0x37)):((char)(nib_h-0x57))));
        nib_l = (nib_l <= '9')?((char)(nib_l-0x30)):(((nib_l<='F')?((char)(nib_l-0x37)):((char)(nib_l-0x57))));
        return (char)((nib_h<<4)+nib_l);
    }


    //Callback Function for Recv the message from POC Lib
    public void OEM_AT_cb(String sData)
    {
        Timber.tag(TAG).d("Poc2 AT Callback: %s", sData);
        int len, i, j=0;
        char[] bytes = sData.toCharArray();

        List<String> lisHex = new ArrayList<>();
        if (bytes.length > 5 && bytes[0] == '+' && bytes[1] == 'P' && bytes[2] == 'O' && bytes[3] == 'C' && bytes[4] == ':') {
            len = bytes.length - 5;
            if (len >= 2) {
                for (i = 0; i < len - 1; i = i + 2) {
                    String temp = Integer.toHexString(Ascii2Char(bytes[i + 5], bytes[i + 6]));

                    lisHex.add(temp.length() == 1 ? "0" + temp : temp);
                }
            }
        } else {
            Timber.tag(TAG).w("OEM_AT_cb: unexpected format, len=%d, data=%s", bytes.length, sData);
        }

        CallBackResolution.at_OEM_AT_cb(lisHex);
    }

    public void OEM_Play_cb(byte[] bytes){
        Timber.tag(TAG).d("OEM_Play_cb: %d bytes", bytes.length);
        if (mAudioTrack == null) {
            initAudioTrack();
        }

        if (mAudioTrack.getPlayState() != AudioTrack.PLAYSTATE_PLAYING){
            mAudioTrack.play();
        }
        mAudioTrack.write(bytes, 0, bytes.length);
    }

    public  void OEM_Play_Start_cb()
    {
        Timber.tag(TAG).e("Play Start!!!!");
    }

    public void OEM_Play_Stop_cb()
    {
        Timber.tag(TAG).e("Play Stop!!!!");
    }

    public  void OEM_Record_Start_cb()
    {
        Timber.tag(TAG).e("Record Start!!!!");
    }

    public void OEM_Record_Stop_cb()
    {
        Timber.tag(TAG).e("Record Stop!!!!");
    }

    public void  OEM_Play_TTS_cb(String sData)
    {
        Timber.tag(TAG).e("Play TTS " + sData);
        CallBackResolution.at_Play_TTS_cb(sData);
    }

    //Define the Function of the AT Command send
    private native void OEM_AT_Send(String strAtCmd);
    private native int OEM_Set_AT_CallBack(String cb);

    private native void OEM_Push_Record_Data(byte[]  data);
    private native int OEM_Set_Play_CallBack(String cb);

    private native int OEM_Set_Play_Start_Callback(String cb);
    private native int OEM_Set_Play_Stop_Callback(String cb);

    private native int OEM_Set_Record_Start_Callback(String cb);
    private native int OEM_Set_Record_Stop_Callback(String cb);

    private native int OEM_Set_TTS_Callback(String cb);

    private native void OEM_Poc_Task_Start();

    private native int OEM_Set_Package_Name(String name);

    public void pttNativeSendRecordCmd(byte[] data) {
        Timber.tag(TAG).d("pttNativeSendRecordCmd: %d bytes", data.length);
        OEM_Push_Record_Data(data);
    }

    public void pttNativeSendAtCmd(String strAtCmd)
    {
        try {
            Timber.tag(TAG).i("AT Send: %s", strAtCmd);
            OEM_AT_Send(strAtCmd);
        } catch (Throwable e) {
            Timber.tag(TAG).e( "Native AT Send failed: " + e.getMessage());
        }
    }

    public void pttNativePocTaskStart()
    {
        try {
            OEM_Poc_Task_Start();
        } catch (Throwable e) {
            Timber.tag(TAG).e(e, "Native PocTaskStart failed");
        }
    }

    public int pttNativeSetAtCallback()
    {
        try {
            return OEM_Set_AT_CallBack("OEM_AT_cb");
        } catch (Throwable e) {
            Timber.tag(TAG).e(e, "Failed to set AT callback");
            return -1;
        }
    }

    public int pttNativeSetPlayCallback()
    {
        try {
            return OEM_Set_Play_CallBack("OEM_Play_cb");
        } catch (Throwable e) {
            Timber.tag(TAG).e(e, "Failed to set Play callback");
            return -1;
        }
    }

    public int pttNativeSetPalyStartCallback()
    {
        try {
            return OEM_Set_Play_Start_Callback("OEM_Play_Start_cb");
        } catch (Throwable e) {
            Timber.tag(TAG).e(e, "Failed to set PlayStart callback");
            return -1;
        }
    }

    public int pttNativeSetPlayStopCallback()
    {
        try {
            return OEM_Set_Play_Stop_Callback("OEM_Play_Stop_cb");
        } catch (Throwable e) {
            Timber.tag(TAG).e(e, "Failed to set PlayStop callback");
            return -1;
        }
    }

    public int pttNativeSetRecordStartCallback()
    {
        try {
            return OEM_Set_Record_Start_Callback("OEM_Record_Start_cb");
        } catch (Throwable e) {
            Timber.tag(TAG).e(e, "Failed to set RecordStart callback");
            return -1;
        }
    }

    public int pttNativeSetRecordStopCallback()
    {
        try {
            return OEM_Set_Record_Stop_Callback("OEM_Record_Stop_cb");
        } catch (Throwable e) {
            Timber.tag(TAG).e(e, "Failed to set RecordStop callback");
            return -1;
        }
    }

    public int pttNativeSetTTSCallback()
    {
        try {
            return OEM_Set_TTS_Callback("OEM_Play_TTS_cb");
        } catch (Throwable e) {
            Timber.tag(TAG).e(e, "Failed to set TTS callback");
            return -1;
        }
    }

    public int pttNativeSetPackageName(String name)
    {
        try {
            return OEM_Set_Package_Name(name);
        } catch (Throwable e) {
            Timber.tag(TAG).e(e, "Failed to set package callback");
            return -1;
        }
    }

    public pttNative() {
        Timber.tag(TAG).d("pttNative instance created");
        initAudioTrack();
    }

    private AudioTrack mAudioTrack;
    public void initAudioTrack() {
        int mAudioMinBufSize = AudioTrack.getMinBufferSize(8000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
        Timber.tag(TAG).d("AudioTrack init: minBufSize=%d", mAudioMinBufSize);

        AudioAttributes audioAttributes = new AudioAttributes.Builder()
                .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION) // 通信场景
                .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) // 内容类型
                .setLegacyStreamType(AudioManager.STREAM_MUSIC) // 设置通话流类型
                .build();

        AudioFormat audioFormat = new AudioFormat.Builder()
                .setSampleRate(8000)
                .setChannelMask(AudioFormat.CHANNEL_OUT_MONO)
                .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
                .build();

        mAudioTrack = new AudioTrack(
                audioAttributes,
                audioFormat,
                mAudioMinBufSize * 4,
                AudioTrack.MODE_STREAM,
                AudioManager.AUDIO_SESSION_ID_GENERATE
        );
        mAudioTrack.setVolume(1.0f);// 设置音量

    }

    public void destory() {
        if (mAudioTrack != null) {
            try {
                if (mAudioTrack.getState() == AudioRecord.STATE_INITIALIZED) {
                    mAudioTrack.stop();
                }
                mAudioTrack.release();
                mAudioTrack = null;
            } catch (Exception e) { Timber.tag(TAG).e(e, "AudioTrack destroy failed"); }
        }
    }

}
