/*
 * Copyright (C) 2014 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 android.hardware.soundtrigger;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;

import android.content.Context;
import android.hardware.soundtrigger.SoundTrigger.GenericRecognitionEvent;
import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel;
import android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionEvent;
import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
import android.media.soundtrigger.SoundTriggerManager;
import android.os.ParcelUuid;
import android.os.ServiceManager;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.SmallTest;

import com.android.internal.app.ISoundTriggerService;

import java.io.DataOutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Random;
import java.util.UUID;

import org.mockito.MockitoAnnotations;

public class GenericSoundModelTest extends AndroidTestCase {
    static final int MSG_DETECTION_ERROR = -1;
    static final int MSG_DETECTION_RESUME = 0;
    static final int MSG_DETECTION_PAUSE = 1;
    static final int MSG_KEYPHRASE_TRIGGER = 2;
    static final int MSG_GENERIC_TRIGGER = 4;

    private Random random = new Random();
    private ArrayList<UUID> loadedModelUuids;
    private ISoundTriggerService soundTriggerService;
    private SoundTriggerManager soundTriggerManager;

    @Override
    public void setUp() throws Exception {
        super.setUp();
        MockitoAnnotations.initMocks(this);

        Context context = getContext();
        soundTriggerService = ISoundTriggerService.Stub.asInterface(
                ServiceManager.getService(Context.SOUND_TRIGGER_SERVICE));
        soundTriggerManager = (SoundTriggerManager) context.getSystemService(
                Context.SOUND_TRIGGER_SERVICE);

        loadedModelUuids = new ArrayList<UUID>();
    }

    @Override
    public void tearDown() throws Exception {
        for (UUID modelUuid : loadedModelUuids) {
            soundTriggerService.deleteSoundModel(new ParcelUuid(modelUuid));
        }
        super.tearDown();
    }

    GenericSoundModel new_sound_model() {
        // Create sound model
        byte[] data = new byte[1024];
        random.nextBytes(data);
        UUID modelUuid = UUID.randomUUID();
        UUID mVendorUuid = UUID.randomUUID();
        return new GenericSoundModel(modelUuid, mVendorUuid, data);
    }

    @SmallTest
    public void testUpdateGenericSoundModel() throws Exception {
        GenericSoundModel model = new_sound_model();

        // Update sound model
        soundTriggerService.updateSoundModel(model);
        loadedModelUuids.add(model.uuid);

        // Confirm it was updated
        GenericSoundModel returnedModel =
                soundTriggerService.getSoundModel(new ParcelUuid(model.uuid));
        assertEquals(model, returnedModel);
    }

    @SmallTest
    public void testDeleteGenericSoundModel() throws Exception {
        GenericSoundModel model = new_sound_model();

        // Update sound model
        soundTriggerService.updateSoundModel(model);
        loadedModelUuids.add(model.uuid);

        // Delete sound model
        soundTriggerService.deleteSoundModel(new ParcelUuid(model.uuid));
        loadedModelUuids.remove(model.uuid);

        // Confirm it was deleted
        GenericSoundModel returnedModel =
                soundTriggerService.getSoundModel(new ParcelUuid(model.uuid));
        assertEquals(null, returnedModel);
    }

    @LargeTest
    public void testStartStopGenericSoundModel() throws Exception {
        GenericSoundModel model = new_sound_model();

        boolean captureTriggerAudio = true;
        boolean allowMultipleTriggers = true;
        RecognitionConfig config = new RecognitionConfig(captureTriggerAudio, allowMultipleTriggers,
                null, null);
        TestRecognitionStatusCallback spyCallback = spy(new TestRecognitionStatusCallback());

        // Update and start sound model recognition
        soundTriggerService.updateSoundModel(model);
        loadedModelUuids.add(model.uuid);
        int r = soundTriggerService.startRecognition(new ParcelUuid(model.uuid), spyCallback,
                config);
        assertEquals("Could Not Start Recognition with code: " + r,
                android.hardware.soundtrigger.SoundTrigger.STATUS_OK, r);

        // Stop recognition
        r = soundTriggerService.stopRecognition(new ParcelUuid(model.uuid), spyCallback);
        assertEquals("Could Not Stop Recognition with code: " + r,
                android.hardware.soundtrigger.SoundTrigger.STATUS_OK, r);
    }

    @LargeTest
    public void testTriggerGenericSoundModel() throws Exception {
        GenericSoundModel model = new_sound_model();

        boolean captureTriggerAudio = true;
        boolean allowMultipleTriggers = true;
        RecognitionConfig config = new RecognitionConfig(captureTriggerAudio, allowMultipleTriggers,
                null, null);
        TestRecognitionStatusCallback spyCallback = spy(new TestRecognitionStatusCallback());

        // Update and start sound model
        soundTriggerService.updateSoundModel(model);
        loadedModelUuids.add(model.uuid);
        soundTriggerService.startRecognition(new ParcelUuid(model.uuid), spyCallback, config);

        // Send trigger to stub HAL
        Socket socket = new Socket(InetAddress.getLocalHost(), 14035);
        DataOutputStream out = new DataOutputStream(socket.getOutputStream());
        out.writeBytes("trig " + model.uuid.toString() + "\r\n");
        out.flush();
        socket.close();

        // Verify trigger was received
        verify(spyCallback, timeout(100)).onGenericSoundTriggerDetected(any());
    }


    public class TestRecognitionStatusCallback extends IRecognitionStatusCallback.Stub {
        @Override
        public void onGenericSoundTriggerDetected(GenericRecognitionEvent recognitionEvent) {
        }

        @Override
        public void onKeyphraseDetected(KeyphraseRecognitionEvent recognitionEvent) {
        }

        @Override
        public void onError(int status) {
        }

        @Override
        public void onRecognitionPaused() {
        }

        @Override
        public void onRecognitionResumed() {
        }
    }
}
