/*
 * Copyright (C) 2010 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.audioquality;

import android.content.Context;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Environment;
import android.util.Log;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

/**
 * File and data utilities for the Audio Verifier.
 */
public class Utils {
    public static final String TAG = "AudioQualityVerifier";
    public static final ByteOrder BYTE_ORDER = ByteOrder.LITTLE_ENDIAN;

    /**
     *  Time delay.
     *
     *  @param ms time in milliseconds to pause for
     */
    public static void delay(int ms) {
        try {
            Thread.sleep(ms);
        } catch (InterruptedException e) {}
    }

    public static String getExternalDir(Context context, Object exp) {
        checkExternalStorageAvailable();
        // API level 8:
        // return context.getExternalFilesDir(null).getAbsolutePath();
        // API level < 8:
        String dir = Environment.getExternalStorageDirectory().getAbsolutePath();
        dir += "/Android/data/" + exp.getClass().getPackage().getName() + "/files";
        checkMakeDir(dir);
        return dir;
    }

    private static void checkExternalStorageAvailable() {
        String state = Environment.getExternalStorageState();
        if (!Environment.MEDIA_MOUNTED.equals(state)) {
            // TODO: Raise a Toast and supply internal storage instead
        }
    }

    private static void checkMakeDir(String dir) {
        File f = new File(dir);
        if (!f.exists()) {
            f.mkdirs();
        }
    }

    /**
     * Convert a string (e.g. the name of an experiment) to something more suitable
     * for use as a filename.
     *
     * @param s the string to be cleaned
     * @return a string which is similar (not necessarily unique) and safe for filename use
     */
    public static String cleanString(String s) {
        StringBuilder sb = new StringBuilder();
        for (char c : s.toCharArray()) {
            if (Character.isWhitespace(c)) sb.append('_');
            else if (Character.isLetterOrDigit(c)) sb.append(c);
        }
        return sb.toString();
    }

    /**
     * Convert a sub-array from bytes to shorts.
     *
     * @param data array of bytes to be converted
     * @param start first index to convert (should be even)
     * @param len number of bytes to convert (should be even)
     * @return an array of half the length, containing shorts
     */
    public static short[] byteToShortArray(byte[] data, int start, int len) {
        short[] samples = new short[len / 2];
        ByteBuffer bb = ByteBuffer.wrap(data, start, len);
        bb.order(BYTE_ORDER);
        for (int i = 0; i < len / 2; i++) {
            samples[i] = bb.getShort();
        }
        return samples;
    }

    /**
     * Convert a byte array to an array of shorts (suitable for the phone test
     * native library's audio sample data).
     *
     * @param data array of bytes to be converted
     * @return an array of half the length, containing shorts
     */
    public static short[] byteToShortArray(byte[] data) {
        int len = data.length / 2;
        short[] samples = new short[len];
        ByteBuffer bb = ByteBuffer.wrap(data);
        bb.order(BYTE_ORDER);
        for (int i = 0; i < len; i++) {
            samples[i] = bb.getShort();
        }
        return samples;
    }

    /**
     * Convert a short array (as returned by the phone test native library)
     * to an array of bytes.
     *
     * @param samples array of shorts to be converted
     * @return an array of twice the length, broken out into bytes
     */
    public static byte[] shortToByteArray(short[] samples) {
        int len = samples.length;
        byte[] data = new byte[len * 2];
        ByteBuffer bb = ByteBuffer.wrap(data);
        bb.order(BYTE_ORDER);
        for (int i = 0; i < len; i++) {
            bb.putShort(samples[i]);
        }
        return data;
    }

    /**
     * Scale the amplitude of an array of samples.
     *
     * @param samples to be scaled
     * @param db decibels to scale up by (may be negative)
     * @return the scaled samples
     */
    public static short[] scale(short[] samples, float db) {
        short[] scaled = new short[samples.length];
        // Convert decibels to a linear ratio:
        double ratio = Math.pow(10.0, db / 20.0);
        for (int i = 0; i < samples.length; i++) {
            scaled[i] = (short) (samples[i] * ratio);
        }
        return scaled;
    }

    /**
     * Read an entire file into memory.
     *
     * @param filename to be opened
     * @return the file data, or null in case of error
     */
    private static byte[] readFile(String filename) {
        FileInputStream fis;
        try {
            fis = new FileInputStream(filename);
        } catch (FileNotFoundException e1) {
            return null;
        }

        File file = new File(filename);
        int len = (int) file.length();
        byte[] data = new byte[len];

        int pos = 0;
        int bytes = 0;
        int count;
        while (pos < len) {
            try {
                count = fis.read(data, pos, len - pos);
            } catch (IOException e) {
                return null;
            }
            if (count < 1) return null;
            pos += count;
        }

        try {
            fis.close();
        } catch (IOException e) {}
        return data;
    }

    /**
     * Read an entire file from an InputStream.
     * Useful as AssetManager returns these.
     *
     * @param stream to read file contents from
     * @return file data
     */
    public static byte[] readFile(InputStream stream) {
        final int CHUNK_SIZE = 10000;
        ByteArrayBuilder bab = new ByteArrayBuilder();
        byte[] buf = new byte[CHUNK_SIZE];
        int count;
        while (true) {
            try {
                count = stream.read(buf, 0, CHUNK_SIZE);
            } catch (IOException e) {
                return null;
            }
            if (count == -1) break; // EOF
            bab.append(buf, count);
        }
        return bab.toByteArray();
    }

    /**
     * Save binary (audio) data to a file.
     *
     * @param filename to be written
     * @param data contents
     */
    public static void saveFile(String filename, byte[] data) {
        try {
            FileOutputStream fos = new FileOutputStream(filename);
            fos.write(data);
            fos.close();
        } catch (IOException e) {
            Log.e(TAG, "Error writing to file " + filename);
        }
    }

    /**
     * Push an entire array of audio data to an AudioTrack.
     *
     * @param at destination
     * @param data to be written
     * @return true if successful, or false on error
     */
    public static boolean writeAudio(AudioTrack at, byte[] data) {
        int pos = 0;
        int len = data.length;
        int count;

        while (pos < len) {
            count = at.write(data, pos, len - pos);
            if (count < 0) return false;
            pos += count;
        }
        at.flush();
        return true;
    }

    /**
     * Determine the number of audio samples in a file
     *
     * @param filename file containing audio data
     * @return number of samples in file, or 0 if file does not exist
     */
    public static int duration(String filename) {
        File file = new File(filename);
        int len = (int) file.length();
        return len / AudioQualityVerifierActivity.BYTES_PER_SAMPLE;
    }

    /**
     * Determine the number of audio samples in a stimulus asset
     *
     * @param context to look up stimulus
     * @param stimNum index number of this stimulus
     * @return number of samples in stimulus
     */
    public static int duration(Context context, int stimNum) {
        byte[] data = AudioAssets.getStim(context, stimNum);
        return data.length / AudioQualityVerifierActivity.BYTES_PER_SAMPLE;
    }

    public static void playRawFile(String filename) {
        byte[] data = readFile(filename);
        if (data == null) {
            Log.e(TAG, "Cannot read " + filename);
            return;
        }
        playRaw(data);
    }

    public static void playStim(Context context, int stimNum) {
        Utils.playRaw(getStim(context, stimNum));
    }

    public static byte[] getStim(Context context, int stimNum) {
        return AudioAssets.getStim(context, stimNum);
    }

    public static byte[] getPinkNoise(Context context, int ampl, int duration) {
        return AudioAssets.getPinkNoise(context, ampl, duration);
    }

    public static void playRaw(byte[] data) {
        Log.i(TAG, "Playing " + data.length + " bytes of pre-recorded audio");
        AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, AudioQualityVerifierActivity.SAMPLE_RATE,
                AudioFormat.CHANNEL_OUT_MONO, AudioQualityVerifierActivity.AUDIO_FORMAT,
                data.length, AudioTrack.MODE_STREAM);
        writeAudio(at, data);
        at.play();
    }

    /**
     * The equivalent of a simplified StringBuilder, but for bytes.
     */
    public static class ByteArrayBuilder {
        private byte[] buf;
        private int capacity, size;

        public ByteArrayBuilder() {
            capacity = 100;
            size = 0;
            buf = new byte[capacity];
        }

        public void append(byte[] b, int nBytes) {
            if (nBytes < 1) return;
            if (size + nBytes > capacity) expandCapacity(size + nBytes);
            System.arraycopy(b, 0, buf, size, nBytes);
            size += nBytes;
        }

        public byte[] toByteArray() {
            byte[] result = new byte[size];
            System.arraycopy(buf, 0, result, 0, size);
            return result;
        }

        private void expandCapacity(int min) {
            capacity *= 2;
            if (capacity < min) capacity = min;
            byte[] expanded = new byte[capacity];
            System.arraycopy(buf, 0, expanded, 0, size);
            buf = expanded;
        }
    }
}
