/*
 * 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.text;

import android.app.Activity;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.FontMetricsInt;
import android.os.Bundle;
import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
import android.perftests.utils.StubActivity;

import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.text.style.ReplacementSpan;
import android.util.ArraySet;

import static android.text.Layout.Alignment.ALIGN_NORMAL;

import java.util.Arrays;
import java.util.Collection;
import java.util.Locale;
import java.util.Random;

import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized.Parameters;
import org.junit.runners.Parameterized;

@LargeTest
@RunWith(Parameterized.class)
public class DynamicLayoutPerfTest {

    @Parameters(name = "{0}")
    public static Collection cases() {
        return Arrays.asList(new Object[][] {
            { "0%", 0.0f},
            { "1%", 0.01f},
            { "5%", 0.05f},
            { "30%", 0.3f},
            { "100%", 1.0f},
        });
    }

    private final String mMetricKey;
    private final float mProbability;
    public DynamicLayoutPerfTest(String metricKey, float probability) {
        mMetricKey = metricKey;
        mProbability = probability;
    }

    private static class MockReplacementSpan extends ReplacementSpan {
        @Override
        public int getSize(Paint paint, CharSequence text, int start, int end, FontMetricsInt fm) {
            return 10;
        }

        @Override
        public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top,
                int y, int bottom, Paint paint) {
        }
    }

    @Rule
    public ActivityTestRule<StubActivity> mActivityRule = new ActivityTestRule(StubActivity.class);

    @Rule
    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();


    private final static String ALPHABETS = "abcdefghijklmnopqrstuvwxyz";

    private SpannableStringBuilder getText() {
        final long seed = 1234567890;
        final Random r = new Random(seed);
        final SpannableStringBuilder builder = new SpannableStringBuilder();

        final int paragraphCount = 100;
        for (int i = 0; i < paragraphCount; i++) {
            final int wordCount = 5 + r.nextInt(20);
            final boolean containsReplacementSpan = r.nextFloat() < mProbability;
            final int replacedWordIndex = containsReplacementSpan ? r.nextInt(wordCount) : -1;
            for (int j = 0; j < wordCount; j++) {
                final int startIndex = builder.length();
                final int wordLength = 1 + r.nextInt(10);
                for (int k = 0; k < wordLength; k++) {
                    char c = ALPHABETS.charAt(r.nextInt(ALPHABETS.length()));
                    builder.append(c);
                }
                if (replacedWordIndex == j) {
                    builder.setSpan(new MockReplacementSpan(), startIndex,
                            builder.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                }
                builder.append(' ');
            }
            builder.append('\n');
        }
        return builder;
    }

    @Test
    public void testGetBlocksAlwaysNeedToBeRedrawn() {
        final SpannableStringBuilder text = getText();
        final DynamicLayout layout = new DynamicLayout(text, new TextPaint(), 1000,
                ALIGN_NORMAL, 0, 0, false);

        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
        final int steps = 10;
        while (state.keepRunning()) {
            for (int i = 0; i < steps; i++) {
                int offset = (text.length() * i) / steps;
                text.insert(offset, "\n");
                text.delete(offset, offset + 1);
                final ArraySet<Integer> set = layout.getBlocksAlwaysNeedToBeRedrawn();
                if (set != null) {
                    for (int j = 0; j < set.size(); j++) {
                        layout.getBlockIndex(set.valueAt(j));
                    }
                }
            }
        }
    }
}
