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

import java.util.ArrayList;

import android.test.AndroidTestCase;
import android.text.SpanWatcher;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;

/**
 * Test {@link SpannableStringBuilder}.
 */
public class SpannableStringBuilderSpanTest extends AndroidTestCase {

    private static final boolean DEBUG = false;

    private SpanSet mSpanSet = new SpanSet();
    private SpanSet mReplacementSpanSet = new SpanSet();
    private int testCounter;

    public void testReplaceWithSpans() {
        testCounter = 0;
        String originals[] = { "", "A", "here", "Well, hello there" };
        String replacements[] = { "", "X", "test", "longer replacement" };

        for (String original: originals) {
            for (String replacement: replacements) {
                replace(original, replacement);
            }
        }
    }

    private void replace(String original, String replacement) {
        PositionSet positionSet = new PositionSet(4);
        positionSet.addPosition(0);
        positionSet.addPosition(original.length() / 3);
        positionSet.addPosition(2 * original.length() / 3);
        positionSet.addPosition(original.length());

        PositionSet replPositionSet = new PositionSet(4);
        replPositionSet.addPosition(0);
        replPositionSet.addPosition(replacement.length() / 3);
        replPositionSet.addPosition(2 * replacement.length() / 3);
        replPositionSet.addPosition(replacement.length());

        for (int s = 0; s < positionSet.size(); s++) {
            for (int e = s; e < positionSet.size(); e++) {
                for (int rs = 0; rs < replPositionSet.size(); rs++) {
                    for (int re = rs; re < replPositionSet.size(); re++) {
                        replaceWithRange(original,
                                positionSet.getPosition(s), positionSet.getPosition(e),
                                replacement,
                                replPositionSet.getPosition(rs), replPositionSet.getPosition(re));
                    }
                }
            }
        }
    }

    private void replaceWithRange(String original, int replaceStart, int replaceEnd,
            String replacement, int replacementStart, int replacementEnd) {
        int flags[] = { Spanned.SPAN_EXCLUSIVE_EXCLUSIVE, Spanned.SPAN_INCLUSIVE_INCLUSIVE,
                Spanned.SPAN_EXCLUSIVE_INCLUSIVE, Spanned.SPAN_INCLUSIVE_EXCLUSIVE };


        for (int flag: flags) {
            replaceWithSpanFlag(original, replaceStart, replaceEnd,
                    replacement, replacementStart, replacementEnd, flag);
        }
    }

    private void replaceWithSpanFlag(String original, int replaceStart, int replaceEnd,
            String replacement, int replacementStart, int replacementEnd, int flag) {

        testCounter++;
        int debugTestNumber = -1;
        if (debugTestNumber >= 0 && testCounter != debugTestNumber) return;

        String subReplacement = replacement.substring(replacementStart, replacementEnd);
        String expected = original.substring(0, replaceStart) +
                subReplacement + original.substring(replaceEnd, original.length());
        if (DEBUG) System.out.println("Replace \"" + original + "\" [" +
                replaceStart + " " + replaceEnd + "] by \"" + subReplacement + "\" -> \"" +
                expected + "\", flag=" + flag + ", test #" + testCounter);

        SpannableStringBuilder originalSpannable = new SpannableStringBuilder(original);
        Spannable replacementSpannable = new SpannableStringBuilder(replacement);

        mSpanSet.initSpans(originalSpannable, replaceStart, replaceEnd, flag);
        mReplacementSpanSet.initSpans(replacementSpannable, replacementStart, replacementEnd, flag);

        originalSpannable.replace(replaceStart, replaceEnd, replacementSpannable,
                replacementStart, replacementEnd);

        assertEquals(expected, originalSpannable.toString());

        checkSpanPositions(originalSpannable, replaceStart, replaceEnd, subReplacement.length(), flag);
        checkReplacementSpanPositions(originalSpannable, replaceStart, replacementSpannable,
                replacementStart, replacementEnd, flag);
    }

    private void checkSpanPositions(Spannable spannable, int replaceStart, int replaceEnd,
            int replacementLength, int flag) {
        int count = 0;
        int replacedLength = replaceEnd - replaceStart;
        int delta = replacementLength - replacedLength;
        boolean textIsReplaced = replacedLength > 0 && replacementLength > 0;
        for (int s = 0; s < mSpanSet.mPositionSet.size(); s++) {
            for (int e = s; e < mSpanSet.mPositionSet.size(); e++) {
                Object span = mSpanSet.mSpans[count];
                int originalStart = mSpanSet.mPositionSet.getPosition(s);
                int originalEnd = mSpanSet.mPositionSet.getPosition(e);
                int start = spannable.getSpanStart(span);
                int end = spannable.getSpanEnd(span);
                int startStyle = mSpanSet.mSpanStartPositionStyle[count];
                int endStyle = mSpanSet.mSpanEndPositionStyle[count];
                count++;

                if (!isValidSpan(originalStart, originalEnd, flag)) continue;

                if (DEBUG) System.out.println("  " + originalStart + "," + originalEnd + " -> " +
                        start + "," + end + " | " + startStyle + " " + endStyle +
                        " delta=" + delta);

                // This is the exception to the following generic code where we need to consider
                // both the start and end styles.
                if (startStyle == SpanSet.INSIDE && endStyle == SpanSet.INSIDE &&
                        flag == Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) {
                    // 0-length spans should have been removed
                    assertEquals(-1, start);
                    assertEquals(-1, end);
                    mSpanSet.mRecorder.assertRemoved(span, originalStart, originalEnd);
                    continue;
                }

                switch (startStyle) {
                    case SpanSet.BEFORE:
                        assertEquals(originalStart, start);
                        break;
                    case SpanSet.INSIDE:
                        switch (flag) {
                            case Spanned.SPAN_EXCLUSIVE_EXCLUSIVE:
                            case Spanned.SPAN_EXCLUSIVE_INCLUSIVE:
                                // start is POINT
                                if (originalStart == replaceStart && textIsReplaced) {
                                    assertEquals(replaceStart, start);
                                } else {
                                    assertEquals(replaceStart + replacementLength, start);
                                }
                                break;
                            case Spanned.SPAN_INCLUSIVE_INCLUSIVE:
                            case Spanned.SPAN_INCLUSIVE_EXCLUSIVE:
                                // start is MARK
                                if (originalStart == replaceEnd && textIsReplaced) {
                                    assertEquals(replaceStart + replacementLength, start);
                                } else {
                                    assertEquals(replaceStart, start);
                                }
                                break;
                            case Spanned.SPAN_PARAGRAPH:
                                fail("TODO");
                                break;
                        }
                        break;
                    case SpanSet.AFTER:
                        assertEquals(originalStart + delta, start);
                        break;
                }

                switch (endStyle) {
                    case SpanSet.BEFORE:
                        assertEquals(originalEnd, end);
                        break;
                    case SpanSet.INSIDE:
                        switch (flag) {
                            case Spanned.SPAN_EXCLUSIVE_EXCLUSIVE:
                            case Spanned.SPAN_INCLUSIVE_EXCLUSIVE:
                                // end is MARK
                                if (originalEnd == replaceEnd && textIsReplaced) {
                                    assertEquals(replaceStart + replacementLength, end);
                                } else {
                                    assertEquals(replaceStart, end);
                                }
                                break;
                            case Spanned.SPAN_INCLUSIVE_INCLUSIVE:
                            case Spanned.SPAN_EXCLUSIVE_INCLUSIVE:
                                // end is POINT
                                if (originalEnd == replaceStart && textIsReplaced) {
                                    assertEquals(replaceStart, end);
                                } else {
                                    assertEquals(replaceStart + replacementLength, end);
                                }
                                break;
                            case Spanned.SPAN_PARAGRAPH:
                                fail("TODO");
                                break;
                        }
                        break;
                    case SpanSet.AFTER:
                        assertEquals(originalEnd + delta, end);
                        break;
                }

                if (start != originalStart || end != originalEnd) {
                    mSpanSet.mRecorder.assertChanged(span, originalStart, originalEnd, start, end);
                } else {
                    mSpanSet.mRecorder.assertUnmodified(span);
                }
            }
        }
    }

    private void checkReplacementSpanPositions(Spannable originalSpannable, int replaceStart,
            Spannable replacementSpannable, int replStart, int replEnd, int flag) {

        // Get all spans overlapping the replacement substring region
        Object[] addedSpans = replacementSpannable.getSpans(replStart, replEnd, Object.class);

        int count = 0;
        for (int s = 0; s < mReplacementSpanSet.mPositionSet.size(); s++) {
            for (int e = s; e < mReplacementSpanSet.mPositionSet.size(); e++) {
                Object span = mReplacementSpanSet.mSpans[count];
                int originalStart = mReplacementSpanSet.mPositionSet.getPosition(s);
                int originalEnd = mReplacementSpanSet.mPositionSet.getPosition(e);
                int start = originalSpannable.getSpanStart(span);
                int end = originalSpannable.getSpanEnd(span);
                count++;

                if (!isValidSpan(originalStart, originalEnd, flag)) continue;

                if (DEBUG) System.out.println("  replacement " + originalStart + "," + originalEnd +
                        " -> " + start + "," + end);

                // There should be no change reported to the replacement string spanWatcher
                mReplacementSpanSet.mRecorder.assertUnmodified(span);

                boolean shouldBeAdded = false;
                for (int i = 0; i < addedSpans.length; i++) {
                    if (addedSpans[i] == span) {
                        shouldBeAdded = true;
                        break;
                    }
                }

                if (shouldBeAdded) {
                    int newStart = Math.max(0, originalStart - replStart) + replaceStart;
                    int newEnd = Math.min(originalEnd, replEnd) - replStart + replaceStart;
                    if (isValidSpan(newStart, newEnd, flag)) {
                        assertEquals(start, newStart);
                        assertEquals(end, newEnd);
                        mSpanSet.mRecorder.assertAdded(span, start, end);
                        continue;
                    }
                }

                mSpanSet.mRecorder.assertUnmodified(span);
            }
        }
    }

    private static boolean isValidSpan(int start, int end, int flag) {
        // Zero length SPAN_EXCLUSIVE_EXCLUSIVE are not allowed
        if (flag == Spanned.SPAN_EXCLUSIVE_EXCLUSIVE && start == end) return false;
        return true;
    }

    private static class PositionSet {
        private int[] mPositions;
        private int mSize;

        PositionSet(int capacity) {
            mPositions = new int[capacity];
            mSize = 0;
        }

        void addPosition(int position) {
            if (mSize == 0 || position > mPositions[mSize - 1]) {
                mPositions[mSize] = position;
                mSize++;
            }
        }

        void clear() {
            mSize = 0;
        }

        int size() {
            return mSize;
        }

        int getPosition(int index) {
            return mPositions[index];
        }
    }

    private static class SpanSet {
        private static final int NB_POSITIONS = 8;

        static final int BEFORE = 0;
        static final int INSIDE = 1;
        static final int AFTER = 2;

        private PositionSet mPositionSet;
        private Object[] mSpans;
        private int[] mSpanStartPositionStyle;
        private int[] mSpanEndPositionStyle;
        private SpanWatcherRecorder mRecorder;

        SpanSet() {
            mPositionSet = new PositionSet(NB_POSITIONS);
            int nbSpans = (NB_POSITIONS * (NB_POSITIONS + 1)) / 2;
            mSpanStartPositionStyle = new int[nbSpans];
            mSpanEndPositionStyle = new int[nbSpans];
            mSpans = new Object[nbSpans];
            for (int i = 0; i < nbSpans; i++) {
                mSpans[i] = new Object();
            }
            mRecorder = new SpanWatcherRecorder();
        }

        static int getPositionStyle(int position, int replaceStart, int replaceEnd) {
            if (position < replaceStart) return BEFORE;
            else if (position <= replaceEnd) return INSIDE;
            else return AFTER;
        }

        /**
         * Creates spans for all the possible interval cases. On short strings, or when the
         * replaced region is at the beginning/end of the text, some of these spans may have an
         * identical range
         */
        void initSpans(Spannable spannable, int rangeStart, int rangeEnd, int flag) {
            mPositionSet.clear();
            mPositionSet.addPosition(0);
            mPositionSet.addPosition(rangeStart / 2);
            mPositionSet.addPosition(rangeStart);
            mPositionSet.addPosition((2 * rangeStart + rangeEnd) / 3);
            mPositionSet.addPosition((rangeStart + 2 * rangeEnd) / 3);
            mPositionSet.addPosition(rangeEnd);
            mPositionSet.addPosition((rangeEnd + spannable.length()) / 2);
            mPositionSet.addPosition(spannable.length());

            int count = 0;
            for (int s = 0; s < mPositionSet.size(); s++) {
                for (int e = s; e < mPositionSet.size(); e++) {
                    int start = mPositionSet.getPosition(s);
                    int end = mPositionSet.getPosition(e);
                    if (isValidSpan(start, end, flag)) {
                        spannable.setSpan(mSpans[count], start, end, flag);
                    }
                    mSpanStartPositionStyle[count] = getPositionStyle(start, rangeStart, rangeEnd);
                    mSpanEndPositionStyle[count] = getPositionStyle(end, rangeStart, rangeEnd);
                    count++;
                }
            }

            // Must be done after all the spans were added, to not record these additions
            spannable.setSpan(mRecorder, 0, spannable.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
            mRecorder.reset(spannable);
        }
    }

    private static class SpanWatcherRecorder implements SpanWatcher {
        private ArrayList<AddedRemoved> mAdded = new ArrayList<AddedRemoved>();
        private ArrayList<AddedRemoved> mRemoved = new ArrayList<AddedRemoved>();
        private ArrayList<Changed> mChanged = new ArrayList<Changed>();

        private Spannable mSpannable;

        private class AddedRemoved {
            Object span;
            int start;
            int end;

            public AddedRemoved(Object span, int start, int end) {
                this.span = span;
                this.start = start;
                this.end = end;
            }
        }

        private class Changed {
            Object span;
            int oldStart;
            int oldEnd;
            int newStart;
            int newEnd;

            public Changed(Object span, int oldStart, int oldEnd, int newStart, int newEnd) {
                this.span = span;
                this.oldStart = oldStart;
                this.oldEnd = oldEnd;
                this.newStart = newStart;
                this.newEnd = newEnd;
            }
        }

        public void reset(Spannable spannable) {
            mSpannable = spannable;
            mAdded.clear();
            mRemoved.clear();
            mChanged.clear();
        }

        @Override
        public void onSpanAdded(Spannable text, Object span, int start, int end) {
            if (text == mSpannable) mAdded.add(new AddedRemoved(span, start, end));
        }

        @Override
        public void onSpanRemoved(Spannable text, Object span, int start, int end) {
            if (text == mSpannable) mRemoved.add(new AddedRemoved(span, start, end));
        }

        @Override
        public void onSpanChanged(Spannable text, Object span, int ostart, int oend, int nstart,
                int nend) {
            if (text == mSpannable) mChanged.add(new Changed(span, ostart, oend, nstart, nend));
        }

        public void assertUnmodified(Object span) {
            for (AddedRemoved added: mAdded) {
                if (added.span == span)
                    fail("Span " + span + " was added and not unmodified");
            }
            for (AddedRemoved removed: mRemoved) {
                if (removed.span == span)
                    fail("Span " + span + " was removed and not unmodified");
            }
            for (Changed changed: mChanged) {
                if (changed.span == span)
                    fail("Span " + span + " was changed and not unmodified");
            }
        }

        public void assertChanged(Object span, int oldStart, int oldEnd, int newStart, int newEnd) {
            for (Changed changed : mChanged) {
                if (changed.span == span) {
                    assertEquals(changed.newStart, newStart);
                    assertEquals(changed.newEnd, newEnd);
                    // TODO previous range is not correctly sent in case a bound was inside the
                    // affected range. See SpannableStringBuilder#sendToSpanWatchers limitation
                    //assertEquals(changed.oldStart, oldStart);
                    //assertEquals(changed.oldEnd, oldEnd);
                    return;
                }
            }
            fail("Span " + span + " was not changed");
        }

        public void assertAdded(Object span, int start, int end) {
            for (AddedRemoved added : mAdded) {
                if (added.span == span) {
                    assertEquals(added.start, start);
                    assertEquals(added.end, end);
                    return;
                }
            }
            fail("Span " + span + " was not added");
        }

        public void assertRemoved(Object span, int start, int end) {
            for (AddedRemoved removed : mRemoved) {
                if (removed.span == span) {
                    assertEquals(removed.start, start);
                    assertEquals(removed.end, end);
                    return;
                }
            }
            fail("Span " + span + " was not removed");
        }
    }

    // TODO Thoroughly test the SPAN_PARAGRAPH span flag.
}
