/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.cts.verifier.audio;

import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.media.AudioDeviceCallback;
import android.media.AudioDeviceInfo;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.TextView;
import android.widget.Toast;

import com.android.cts.verifier.PassFailButtons;
import com.android.cts.verifier.R;  // needed to access resource in CTSVerifier project namespace.

import java.util.List;

public class ProAudioActivity
        extends PassFailButtons.Activity
        implements View.OnClickListener {
    private static final String TAG = ProAudioActivity.class.getName();
    private static final boolean DEBUG = false;

    // Flags
    private boolean mClaimsProAudio;
    private boolean mClaimsLowLatencyAudio;    // CDD ProAudio section C-1-1
    private boolean mClaimsMIDI;               // CDD ProAudio section C-1-4
    private boolean mClaimsUSBHostMode;        // CDD ProAudio section C-1-3
    private boolean mClaimsUSBPeripheralMode;  // CDD ProAudio section C-1-3
    private boolean mClaimsHDMI;               // CDD ProAudio section C-1-3

    // Values
    private static final double LATENCY_MS_LIMIT = 20.0; // CDD ProAudio section C-1-2
    private double mRoundTripLatency;
    private static final double CONFIDENCE_LIMIT = 0.75; // TBD
    private double mRoundTripConfidence;

    // Peripheral(s)
    AudioManager mAudioManager;
    private boolean mIsPeripheralAttached;  // CDD ProAudio section C-1-3
    private AudioDeviceInfo mOutputDevInfo;
    private AudioDeviceInfo mInputDevInfo;

    private AudioDeviceInfo mHDMIDeviceInfo;

    // Widgets
    TextView mInputDeviceTxt;
    TextView mOutputDeviceTxt;
    TextView mRoundTripLatencyTxt;
    TextView mRoundTripConfidenceTxt;
    TextView mHDMISupportLbl;

    CheckBox mClaimsHDMICheckBox;

    // Borrowed from PassFailButtons.java
    private static final int INFO_DIALOG_ID = 1337;
    private static final String INFO_DIALOG_TITLE_ID = "infoDialogTitleId";
    private static final String INFO_DIALOG_MESSAGE_ID = "infoDialogMessageId";

    public ProAudioActivity() {
        super();
    }

    private boolean claimsProAudio() {
        return getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_PRO);
    }

    private boolean claimsLowLatencyAudio() {
        // CDD Section C-1-1: android.hardware.audio.low_latency
        return getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY);
    }

    private boolean claimsMIDI() {
        // CDD Section C-1-4: android.software.midi
        return getPackageManager().hasSystemFeature(PackageManager.FEATURE_MIDI);
    }

    private boolean claimsUSBHostMode() {
        return getPackageManager().hasSystemFeature(PackageManager.FEATURE_USB_HOST);
    }

    private boolean claimsUSBPeripheralMode() {
        return getPackageManager().hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY);
    }

    private void showConnectedAudioPeripheral() {
        mInputDeviceTxt.setText(
                mInputDevInfo != null ? mInputDevInfo.getProductName().toString()
                        : "");
        mOutputDeviceTxt.setText(
                mOutputDevInfo != null ? mOutputDevInfo.getProductName().toString()
                        : "");
    }

    // HDMI Stuff
    private boolean isHDMIValid() {
        if (mHDMIDeviceInfo == null) {
            return false;
        }

        // MUST support output in stereo and eight channels...
        boolean has2Chans = false;
        boolean has8Chans = false;
        int[] channelCounts = mHDMIDeviceInfo.getChannelCounts();
        for (int count : channelCounts) {
            if (count == 2) {
                has2Chans = true;
            } else if (count == 8) {
                has8Chans = true;
            }
        }
        if (!has2Chans || !has8Chans) {
            return false;
        }

        // at 20-bit or 24-bit depth
        boolean hasFloatEncoding = false;
        int[] encodings = mHDMIDeviceInfo.getEncodings();
        for (int encoding : encodings) {
            if (encoding == AudioFormat.ENCODING_PCM_FLOAT) {
                hasFloatEncoding = true;
                break;
            }
        }
        if (!hasFloatEncoding) {
            return false;
        }

         // and 192 kHz
        boolean has192K = false;
        int[] sampleRates = mHDMIDeviceInfo.getSampleRates();
        for (int rate : sampleRates) {
            if (rate >= 192000) {
                has192K = true;
            }
        }
        if (!has192K) {
            return false;
        }

        // without bit-depth loss or resampling (hmmmmm....).

        return true;
    }

    private void calculatePass() {
        boolean hasPassed = !mClaimsProAudio ||
                (mClaimsLowLatencyAudio && mClaimsMIDI &&
                mClaimsUSBHostMode && mClaimsUSBPeripheralMode &&
                (!mClaimsHDMI || isHDMIValid()) &&
                mOutputDevInfo != null && mInputDevInfo != null &&
                mRoundTripLatency != 0.0 && mRoundTripLatency <= LATENCY_MS_LIMIT &&
                mRoundTripConfidence >= CONFIDENCE_LIMIT);
        getPassButton().setEnabled(hasPassed);
    }

    //
    // Loopback App Stuff
    //
    private final static String LOOPBACK_PACKAGE_NAME = "org.drrickorang.loopback";

    // Test Intents
    // From Loopback App LoobackActivity.java
    private static final String INTENT_TEST_TYPE = "TestType";

    // from Loopback App Constant.java
    public static final int LOOPBACK_PLUG_AUDIO_THREAD_TEST_TYPE_LATENCY = 222;

    public boolean isLoopbackAppInstalled() {
        try {
            getPackageManager().getPackageInfo(
                    LOOPBACK_PACKAGE_NAME, PackageManager.GET_ACTIVITIES);
            return true;
        } catch (PackageManager.NameNotFoundException e) {
            // This indicates that the specified app (Loopback in this case) is NOT installed
            // fall through...
        }
        return false;
    }

    // arbitrary request code
    private static final int LATENCY_RESULTS_REQUEST_CODE = 1;
    private static final String KEY_CTSINVOCATION = "CTS-Test";
    private static final String KEY_ROUND_TRIP_TIME = "RoundTripTime";
    private static final String KEY_ROUND_TRIP_CONFIDENCE = "Confidence";

    // We may need to iterate and average round-trip measurements
    // So add this plumbing though NOT USED.
    private static final String KEY_NUMITERATIONS = "NumIterations";
    private static final int NUM_ROUNDTRIPITERATIONS = 3;

    private void runRoundTripTest() {
        if (!isLoopbackAppInstalled()) {
            Toast.makeText(this, "Loopback App not installed", Toast.LENGTH_SHORT).show();
            return;
        }

        if (!mIsPeripheralAttached) {
            Toast.makeText(this, "Please connect a USB audio peripheral with loopback cables" +
                    " before running the latency test.",
                    Toast.LENGTH_SHORT).show();
            return;
        }

        mRoundTripLatency = 0.0;
        mRoundTripConfidence = 0.0;
        Intent intent = new Intent(Intent.CATEGORY_LAUNCHER);
        intent.setComponent(
            new ComponentName(LOOPBACK_PACKAGE_NAME,LOOPBACK_PACKAGE_NAME + ".LoopbackActivity"));

        intent.putExtra(KEY_CTSINVOCATION, "CTS-Verifier Invocation");
        intent.putExtra(INTENT_TEST_TYPE, LOOPBACK_PLUG_AUDIO_THREAD_TEST_TYPE_LATENCY);
        intent.putExtra(KEY_NUMITERATIONS, NUM_ROUNDTRIPITERATIONS);

        startActivityForResult(intent, LATENCY_RESULTS_REQUEST_CODE);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // Check which request we're responding to
        if (resultCode == RESULT_OK) {
            Toast.makeText(this, "Round Trip Test Complete.", Toast.LENGTH_SHORT).show();
            if (requestCode == LATENCY_RESULTS_REQUEST_CODE) {
                Bundle extras = data != null ? data.getExtras() : null;
                if (extras != null) {
                    mRoundTripLatency =  extras.getDouble(KEY_ROUND_TRIP_TIME);
                    mRoundTripLatencyTxt.setText(String.format("%.2f ms", mRoundTripLatency));
                    mRoundTripConfidence = extras.getDouble(KEY_ROUND_TRIP_CONFIDENCE);
                    mRoundTripConfidenceTxt.setText(String.format("%.2f", mRoundTripConfidence));
                }
            }
            calculatePass();
        } else {
            Toast.makeText(this, "Round Trip Test Canceled.", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.pro_audio);

        mAudioManager = (AudioManager)getSystemService(AUDIO_SERVICE);
        mAudioManager.registerAudioDeviceCallback(new ConnectListener(), new Handler());

        setPassFailButtonClickListeners();
        setInfoResources(R.string.proaudio_test, R.string.proaudio_info, -1);

        mClaimsProAudio = claimsProAudio();
        ((TextView)findViewById(R.id.proAudioHasProAudioLbl)).setText("" + mClaimsProAudio);

        if (!mClaimsProAudio) {
            Bundle args = new Bundle();
            args.putInt(INFO_DIALOG_TITLE_ID, R.string.pro_audio_latency_test);
            args.putInt(INFO_DIALOG_MESSAGE_ID, R.string.audio_proaudio_nopa_message);
            showDialog(INFO_DIALOG_ID, args);
        }

        mClaimsLowLatencyAudio = claimsLowLatencyAudio();
        ((TextView)findViewById(R.id.proAudioHasLLALbl)).setText("" + mClaimsLowLatencyAudio);

        mClaimsMIDI = claimsMIDI();
        ((TextView)findViewById(R.id.proAudioHasMIDILbl)).setText("" + mClaimsMIDI);

        mClaimsUSBHostMode = claimsUSBHostMode();
        ((TextView)findViewById(R.id.proAudioMidiHasUSBHostLbl)).setText("" + mClaimsUSBHostMode);

        mClaimsUSBPeripheralMode = claimsUSBPeripheralMode();
        ((TextView)findViewById(
                R.id.proAudioMidiHasUSBPeripheralLbl)).setText("" + mClaimsUSBPeripheralMode);

        // Connected Device
        mInputDeviceTxt = ((TextView)findViewById(R.id.proAudioInputLbl));
        mOutputDeviceTxt = ((TextView)findViewById(R.id.proAudioOutputLbl));

        // Round-trip Latency
        mRoundTripLatencyTxt = (TextView)findViewById(R.id.proAudioRoundTripLbl);
        mRoundTripConfidenceTxt = (TextView)findViewById(R.id.proAudioConfidenceLbl);
        ((Button)findViewById(R.id.proAudio_runRoundtripBtn)).setOnClickListener(this);

        // HDMI
        mHDMISupportLbl = (TextView)findViewById(R.id.proAudioHDMISupportLbl);
        mClaimsHDMICheckBox = (CheckBox)findViewById(R.id.proAudioHasHDMICheckBox);
        mClaimsHDMICheckBox.setOnClickListener(this);

        calculatePass();
    }

    private void scanPeripheralList(AudioDeviceInfo[] devices) {
        // CDD Section C-1-3: USB port, host-mode support

        // Can't just use the first record because then we will only get
        // Source OR sink, not both even on devices that are both.
        mOutputDevInfo = null;
        mInputDevInfo = null;

        // Any valid peripherals
        // Do we leave in the Headset test to support a USB-Dongle?
        for (AudioDeviceInfo devInfo : devices) {
            if (devInfo.getType() == AudioDeviceInfo.TYPE_USB_DEVICE ||     // USB Peripheral
                devInfo.getType() == AudioDeviceInfo.TYPE_USB_HEADSET ||    // USB dongle+LBPlug
                devInfo.getType() == AudioDeviceInfo.TYPE_WIRED_HEADSET || // Loopback Plug?
                devInfo.getType() == AudioDeviceInfo.TYPE_AUX_LINE) { // Aux-cable loopback?
                if (devInfo.isSink()) {
                    mOutputDevInfo = devInfo;
                }
                if (devInfo.isSource()) {
                    mInputDevInfo = devInfo;
                }
            } else if (devInfo.isSink() && devInfo.getType() == AudioDeviceInfo.TYPE_HDMI) {
                mHDMIDeviceInfo = devInfo;
            }
        }

        mIsPeripheralAttached = mOutputDevInfo != null || mInputDevInfo != null;
        showConnectedAudioPeripheral();

        if (mHDMIDeviceInfo != null) {
            mClaimsHDMICheckBox.setChecked(true);
            mHDMISupportLbl.setText(getResources().getString(
                    isHDMIValid() ? R.string.pass_button_text : R.string.fail_button_text));
        }
        mHDMISupportLbl.setText(getResources().getString(R.string.audio_proaudio_NA));

        calculatePass();
    }

    private class ConnectListener extends AudioDeviceCallback {
        /*package*/ ConnectListener() {}

        //
        // AudioDevicesManager.OnDeviceConnectionListener
        //
        @Override
        public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) {
            scanPeripheralList(mAudioManager.getDevices(AudioManager.GET_DEVICES_ALL));
        }

        @Override
        public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) {
            scanPeripheralList(mAudioManager.getDevices(AudioManager.GET_DEVICES_ALL));
        }
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
        case R.id.proAudio_runRoundtripBtn:
            runRoundTripTest();
            break;

        case R.id.proAudioHasHDMICheckBox:
            if (mClaimsHDMICheckBox.isChecked()) {
                AlertDialog.Builder builder =
                        new AlertDialog.Builder(this, android.R.style.Theme_Material_Dialog_Alert);
                builder.setTitle(getResources().getString(R.string.proaudio_hdmi_infotitle));
                builder.setMessage(getResources().getString(R.string.proaudio_hdmi_message));
                builder.setPositiveButton(android.R.string.yes,
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {}
                 });
                builder.setIcon(android.R.drawable.ic_dialog_alert);
                builder.show();

                mClaimsHDMI = true;
                mHDMISupportLbl.setText(getResources().getString(R.string.audio_proaudio_pending));
            } else {
                mClaimsHDMI = false;
                mHDMISupportLbl.setText(getResources().getString(R.string.audio_proaudio_NA));
            }
            break;
        }
    }
}
