/*
 * 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 com.android.cts.tvproviderperf;

import android.content.ComponentName;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.OperationApplicationException;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.cts.util.CtsAndroidTestCase;
import android.media.tv.TvContract;
import android.media.tv.TvContract.Channels;
import android.media.tv.TvContract.Programs;
import android.net.Uri;
import android.os.RemoteException;

import com.android.cts.util.MeasureRun;
import com.android.cts.util.MeasureTime;
import com.android.cts.util.ResultType;
import com.android.cts.util.ResultUnit;
import com.android.cts.util.ReportLog;
import com.android.cts.util.TimeoutReq;
import com.android.cts.util.Stat;

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

/**
 * Test performance of TvProvider on a device. TvProvider typically handles hundreds of
 * thousands of records periodically, so it is desirable to have performance under a reasonable
 * bar.
 */
public class TvProviderPerfTest extends CtsAndroidTestCase {
    private static final int TRANSACTION_RUNS = 100;
    private static final int QUERY_RUNS = 10;

    private ContentResolver mContentResolver;
    private String mInputId;
    private boolean mHasTvInputFramework;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mHasTvInputFramework = getContext().getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_LIVE_TV);
        if (!mHasTvInputFramework) return;
        mContentResolver = getContext().getContentResolver();
        mInputId = TvContract.buildInputId(new ComponentName(getContext(), getClass()));
    }

    @Override
    protected void tearDown() throws Exception {
        try {
            if (!mHasTvInputFramework) return;
            mContentResolver.delete(Programs.CONTENT_URI, null, null);
            mContentResolver.delete(Channels.CONTENT_URI, null, null);
        } finally {
            super.tearDown();
        }
    }

    @TimeoutReq(minutes = 8)
    public void testChannels() throws Exception {
        if (!mHasTvInputFramework) return;
        double[] averages = new double[5];

        // Insert
        final ArrayList<ContentProviderOperation> operations = new ArrayList<>();
        final int TRANSACTION_SIZE = 1000;
        double[] applyBatchTimes = MeasureTime.measure(TRANSACTION_RUNS, new MeasureRun() {
            @Override
            public void run(int i) {
                operations.clear();
                for (int j = 0; j < TRANSACTION_SIZE; ++j) {
                    ContentValues values = new ContentValues();
                    values.put(Channels.COLUMN_INPUT_ID, mInputId);
                    values.put(Channels.COLUMN_SERVICE_TYPE,
                            Channels.SERVICE_TYPE_AUDIO_VIDEO);
                    values.put(Channels.COLUMN_TYPE, Channels.TYPE_OTHER);
                    operations.add(
                            ContentProviderOperation.newInsert(Channels.CONTENT_URI)
                            .withValues(values).build());
                }
                try {
                    mContentResolver.applyBatch(TvContract.AUTHORITY, operations);
                } catch (OperationApplicationException | RemoteException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        getReportLog().printArray("Elapsed time for insert: ",
                applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
        averages[0] = Stat.getAverage(applyBatchTimes);

        // Update
        final String[] projection = { Channels._ID };
        try (final Cursor cursor = mContentResolver.query(Channels.CONTENT_URI,
                projection, null, null, null)) {
            applyBatchTimes = MeasureTime.measure(TRANSACTION_RUNS, new MeasureRun() {
                @Override
                public void run(int i) {
                    operations.clear();
                    for (int j = 0; j < TRANSACTION_SIZE && cursor.moveToNext(); ++j) {
                        Uri channelUri = TvContract.buildChannelUri(cursor.getLong(0));
                        String number = Integer.toString(i * TRANSACTION_SIZE + j);
                        operations.add(
                                ContentProviderOperation.newUpdate(channelUri)
                                .withValue(Channels.COLUMN_DISPLAY_NUMBER, number)
                                .build());
                    }
                    try {
                        mContentResolver.applyBatch(TvContract.AUTHORITY, operations);
                    } catch (OperationApplicationException | RemoteException e) {
                        throw new RuntimeException(e);
                    }
                }
            });
        }
        getReportLog().printArray("Elapsed time for update: ",
                applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
        averages[1] = Stat.getAverage(applyBatchTimes);

        // Query channels
        applyBatchTimes = MeasureTime.measure(QUERY_RUNS, new MeasureRun() {
            @Override
            public void run(int i) {
                try (Cursor cursor = mContentResolver.query(Channels.CONTENT_URI, null, null,
                        null, null)) {
                    while (cursor.moveToNext()) {
                        // Do nothing. Just iterate all the items.
                    }
                }
            }
        });
        getReportLog().printArray("Elapsed time for query (channels): ",
                applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
        averages[2] = Stat.getAverage(applyBatchTimes);

        // Query a channel
        try (final Cursor cursor = mContentResolver.query(Channels.CONTENT_URI,
                projection, null, null, null)) {
            final Uri channelUri = TvContract.buildChannelUri(cursor.getLong(0));
            applyBatchTimes = MeasureTime.measure(QUERY_RUNS, new MeasureRun() {
                @Override
                public void run(int i) {
                    assertTrue(cursor.moveToNext());
                    try (Cursor c = mContentResolver.query(channelUri, null, null, null, null)) {
                        while (c.moveToNext()) {
                            // Do nothing. Just iterate all the items.
                        }
                    }
                }
            });
        }
        getReportLog().printArray("Elapsed time for query (a channel): ",
                applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
        averages[3] = Stat.getAverage(applyBatchTimes);

        // Delete
        applyBatchTimes = MeasureTime.measure(1, new MeasureRun() {
            @Override
            public void run(int i) {
                mContentResolver.delete(TvContract.buildChannelsUriForInput(mInputId), null, null);
            }
        });
        getReportLog().printArray("Elapsed time for delete: ",
                applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
        averages[4] = Stat.getAverage(applyBatchTimes);

        getReportLog().printArray("Average elapsed time for insert, update, query (channels), "
                + "query (a channel), delete: ",
                averages, ResultType.LOWER_BETTER, ResultUnit.MS);
    }

    @TimeoutReq(minutes = 12)
    public void testPrograms() throws Exception {
        if (!mHasTvInputFramework) return;
        double[] averages = new double[7];

        // Prepare (insert channels)
        final ArrayList<ContentProviderOperation> operations = new ArrayList<>();
        final int TRANSACTION_SIZE = 1000;
        final int NUM_CHANNELS = 100;
        final List<Uri> channelUris = new ArrayList<>();

        operations.clear();
        for (int i = 0; i < NUM_CHANNELS; ++i) {
            ContentValues values = new ContentValues();
            values.put(Channels.COLUMN_INPUT_ID, mInputId);
            values.put(Channels.COLUMN_SERVICE_TYPE,
                    Channels.SERVICE_TYPE_AUDIO_VIDEO);
            values.put(Channels.COLUMN_TYPE, Channels.TYPE_OTHER);
            operations.add(
                    ContentProviderOperation.newInsert(Channels.CONTENT_URI)
                    .withValues(values).build());
        }
        try {
            ContentProviderResult[] results =
                    mContentResolver.applyBatch(TvContract.AUTHORITY, operations);
            for (ContentProviderResult result : results) {
                channelUris.add(result.uri);
            }
        } catch (OperationApplicationException | RemoteException e) {
            throw new RuntimeException(e);
        }

        // Insert
        double[] applyBatchTimes = MeasureTime.measure(NUM_CHANNELS, new MeasureRun() {
            @Override
            public void run(int i) {
                operations.clear();
                Uri channelUri = channelUris.get(i);
                long channelId = ContentUris.parseId(channelUri);
                for (int j = 0; j < TRANSACTION_SIZE; ++j) {
                    ContentValues values = new ContentValues();
                    values.put(Programs.COLUMN_CHANNEL_ID, channelId);
                    operations.add(
                            ContentProviderOperation.newInsert(Programs.CONTENT_URI)
                            .withValues(values).build());
                }
                try {
                    mContentResolver.applyBatch(TvContract.AUTHORITY, operations);
                } catch (OperationApplicationException | RemoteException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        getReportLog().printArray("Elapsed time for insert: ",
                applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
        averages[0] = Stat.getAverage(applyBatchTimes);

        // Update
        final long PROGRAM_DURATION_MS = 60 * 1000;
        final String[] projection = { Programs._ID };
        applyBatchTimes = MeasureTime.measure(NUM_CHANNELS, new MeasureRun() {
            @Override
            public void run(int i) {
                Uri channelUri = channelUris.get(i);
                operations.clear();
                try (Cursor cursor = mContentResolver.query(
                        TvContract.buildProgramsUriForChannel(channelUri),
                        projection, null, null, null)) {
                    long startTimeMs = 0;
                    long endTimeMs = 0;
                    while (cursor.moveToNext()) {
                        Uri programUri = TvContract.buildProgramUri(cursor.getLong(0));
                        endTimeMs += PROGRAM_DURATION_MS;
                        operations.add(
                                ContentProviderOperation.newUpdate(programUri)
                                .withValue(Programs.COLUMN_START_TIME_UTC_MILLIS, startTimeMs)
                                .withValue(Programs.COLUMN_END_TIME_UTC_MILLIS, endTimeMs)
                                .build());
                        startTimeMs = endTimeMs;
                    }
                }
                try {
                    mContentResolver.applyBatch(TvContract.AUTHORITY, operations);
                } catch (OperationApplicationException | RemoteException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        getReportLog().printArray("Elapsed time for update: ",
                applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
        averages[1] = Stat.getAverage(applyBatchTimes);

        // Query programs
        applyBatchTimes = MeasureTime.measure(QUERY_RUNS, new MeasureRun() {
            @Override
            public void run(int i) {
                try (Cursor cursor = mContentResolver.query(Programs.CONTENT_URI, null, null,
                        null, null)) {
                    while (cursor.moveToNext()) {
                        // Do nothing. Just iterate all the items.
                    }
                }
            }
        });
        getReportLog().printArray("Elapsed time for query (programs): ",
                applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
        averages[2] = Stat.getAverage(applyBatchTimes);

        // Query programs with selection
        applyBatchTimes = MeasureTime.measure(QUERY_RUNS, new MeasureRun() {
            @Override
            public void run(int i) {
                Uri channelUri = channelUris.get(i);
                try (Cursor cursor = mContentResolver.query(
                        TvContract.buildProgramsUriForChannel(
                                channelUri, 0,
                                PROGRAM_DURATION_MS * TRANSACTION_SIZE / 2),
                        null, null, null, null)) {
                    while (cursor.moveToNext()) {
                        // Do nothing. Just iterate all the items.
                    }
                }
            }
        });
        getReportLog().printArray("Elapsed time for query (programs with selection): ",
                applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
        averages[3] = Stat.getAverage(applyBatchTimes);

        // Query a program
        try (final Cursor cursor = mContentResolver.query(Programs.CONTENT_URI,
                projection, null, null, null)) {
            final Uri programUri = TvContract.buildProgramUri(cursor.getLong(0));
            applyBatchTimes = MeasureTime.measure(QUERY_RUNS, new MeasureRun() {
                @Override
                public void run(int i) {
                    assertTrue(cursor.moveToNext());
                    try (Cursor c = mContentResolver.query(programUri, null, null, null, null)) {
                        while (c.moveToNext()) {
                            // Do nothing. Just iterate all the items.
                        }
                    }
                }
            });
        }
        getReportLog().printArray("Elapsed time for query (a program): ",
                applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
        averages[4] = Stat.getAverage(applyBatchTimes);

        // Delete programs
        applyBatchTimes = MeasureTime.measure(NUM_CHANNELS, new MeasureRun() {
            @Override
            public void run(int i) {
                Uri channelUri = channelUris.get(i);
                mContentResolver.delete(
                        TvContract.buildProgramsUriForChannel(
                                channelUri,
                                PROGRAM_DURATION_MS * TRANSACTION_SIZE / 2,
                                PROGRAM_DURATION_MS * TRANSACTION_SIZE),
                        null, null);
            }
        });
        getReportLog().printArray("Elapsed time for delete programs: ",
                applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
        averages[5] = Stat.getAverage(applyBatchTimes);

        // Delete channels
        applyBatchTimes = MeasureTime.measure(NUM_CHANNELS, new MeasureRun() {
            @Override
            public void run(int i) {
                Uri channelUri = channelUris.get(i);
                mContentResolver.delete(channelUri, null, null);
            }
        });
        getReportLog().printArray("Elapsed time for delete channels: ",
                applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
        averages[6] = Stat.getAverage(applyBatchTimes);

        getReportLog().printArray("Average elapsed time for insert, update, query (programs), "
                + "query (programs with selection), query (a channel), delete (channels), "
                + "delete (programs): ",
                averages, ResultType.LOWER_BETTER, ResultUnit.MS);
    }
}
