/*
 * Copyright (C) 2016 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.mediastress.cts.preconditions.app;

import android.app.Instrumentation;
import android.media.MediaFormat;
import android.os.Bundle;
import android.util.Log;

import androidx.test.InstrumentationRegistry;

import com.android.compatibility.common.util.DynamicConfigDeviceSide;
import com.android.compatibility.common.util.MediaUtils;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Test class that uses device-side media APIs to determine up to which resolution MediaPreparer
 * should copy media files for CtsMediaStressTestCases.
 */
@RunWith(JUnit4.class)
public class MediaPreparerAppTest {

    private static final String TAG = MediaPreparerAppTest.class.getSimpleName();

    /** The module name used to retrieve Dynamic Configuration data */
    private static final String MODULE_NAME = "CtsMediaStressTestCases";

    /** The default (minimum) resolution of media file to copy to the device */
    private static final int DEFAULT_MAX_WIDTH = 480;
    private static final int DEFAULT_MAX_HEIGHT = 360;

    /** Instrumentation status code used to write resolution to metrics */
    private static final int INST_STATUS_IN_PROGRESS = 2;

    /** Helper class for generating and retrieving width-height pairs */
    private static final class Resolution {
        // regex that matches a resolution string
        private static final String PATTERN = "(\\d+)x(\\d+)";
        // group indices for accessing resolution witdh/height from a Matcher created from PATTERN
        private static final int WIDTH_INDEX = 1;
        private static final int HEIGHT_INDEX = 2;

        private final int width;
        private final int height;

        private Resolution(int width, int height) {
            this.width = width;
            this.height = height;
        }

        private Resolution(String resolution) {
            Pattern pattern = Pattern.compile(PATTERN);
            Matcher matcher = pattern.matcher(resolution);
            matcher.find();
            this.width = Integer.parseInt(matcher.group(WIDTH_INDEX));
            this.height = Integer.parseInt(matcher.group(HEIGHT_INDEX));
        }

        @Override
        public String toString() {
            return String.format("%dx%d", width, height);
        }
    }

    @Test
    public void testGetResolutions() throws Exception {
        String moduleName = InstrumentationRegistry.getArguments().getString("module-name");
        if (moduleName == null) {
            moduleName = MODULE_NAME;
            Log.i(TAG, "module-name argument is null. Using the default module name: "
                    + moduleName);
        } else {
            Log.i(TAG, "module-name is set from the argument: " + moduleName);
        }
        Resolution maxRes = new Resolution(DEFAULT_MAX_WIDTH, DEFAULT_MAX_HEIGHT);
        DynamicConfigDeviceSide config = new DynamicConfigDeviceSide(moduleName);
        for (String key : config.keySet()) {
            int width = 0;
            int height = 0;
            for (MediaFormat format : stringsToFormats(config.getValues(key))) {
                try {
                    width = Math.max(width, format.getInteger(MediaFormat.KEY_WIDTH));
                    height = Math.max(height, format.getInteger(MediaFormat.KEY_HEIGHT));
                } catch (NullPointerException | ClassCastException e) {
                    // audio format, or invalid format created by unrelated dynamic config entry
                    // simply continue in this case
                }
            }
            Resolution fileResolution = new Resolution(width, height);
            // if the file is of greater resolution than maxRes, check for support
            if (fileResolution.width > maxRes.width) {
                boolean supported = true;
                for (MediaFormat format : stringsToFormats(config.getValues(key))) {
                    supported &= MediaUtils.checkDecoderForFormat(format);
                }
                if (supported) {
                    // update if all MediaFormats for file are supported by device
                    maxRes = fileResolution;
                }
            }
        }
        // write resolution string to metrics
        Instrumentation inst = InstrumentationRegistry.getInstrumentation();
        Bundle maxResBundle = new Bundle();
        maxResBundle.putString("resolution", maxRes.toString());
        inst.sendStatus(INST_STATUS_IN_PROGRESS, maxResBundle);
    }

    /**
     * Converts string representations of MediaFormats into actual MediaFormats
     * @param formatStrings a list of string representations of MediaFormats. Each input string
     * may represent one or more MediaFormats
     * @return a list of MediaFormats
     */
    private List<MediaFormat> stringsToFormats(List<String> formatStrings) {
        List<MediaFormat> formats = new ArrayList<MediaFormat>();
        for (String formatString : formatStrings) {
            for (String trackFormatString : formatString.split(";")) {
                formats.add(parseTrackFormat(trackFormatString));
            }
        }
        return formats;
    }

    /**
     * Converts a single media track format string into a MediaFormat object
     * @param trackFormatString a string representation of the format of one media track
     * @return a MediaFormat
     */
    private static MediaFormat parseTrackFormat(String trackFormatString) {
        MediaFormat format = new MediaFormat();
        format.setString(MediaFormat.KEY_MIME, "");
        for (String entry : trackFormatString.split(",")) {
            String[] kv = entry.split("=");
            if (kv.length < 2) {
                continue;
            }
            String k = kv[0];
            String v = kv[1];
            try {
                format.setInteger(k, Integer.parseInt(v));
            } catch(NumberFormatException e) {
                format.setString(k, v);
            }
        }
        return format;
    }
}
