/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.jackrabbit.oak.commons;

import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.TreeSet;

import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.base.StandardSystemProperty;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import org.apache.commons.io.LineIterator;
import org.apache.jackrabbit.oak.commons.FileIOUtils.FileLineDifferenceIterator;
import org.jetbrains.annotations.Nullable;
import org.junit.Test;

import static java.util.Arrays.asList;
import static org.apache.jackrabbit.oak.commons.sort.EscapeUtils.escapeLineBreak;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

public class FileLineDifferenceIteratorTest {
    
    @Test
    public void testRandomized() throws Exception {
        Random r = new Random(0);
        for (int i = 0; i < 10000; i++) {
            TreeSet<String> marked = new TreeSet<String>();
            TreeSet<String> all = new TreeSet<String>();
            TreeSet<String> diff = new TreeSet<String>();
            int size = r.nextInt(5);
            for (int a = 0; a < size; a++) {
                marked.add("" + r.nextInt(10));
            }
            size = r.nextInt(5);
            for (int a = 0; a < size; a++) {
                all.add("" + r.nextInt(10));
            }
            diff.addAll(all);
            diff.removeAll(marked);
            String m = marked.toString().replaceAll("[ \\[\\]]", "");
            String a = all.toString().replaceAll("[ \\[\\]]", "");
            assertDiff(m, a,
                    new ArrayList<String>(diff));
        }
    }
    
    @Test
    public void testNoDiff() throws Exception {
        assertDiff("a,b,c", "a,b,c", Collections.<String> emptyList());
        assertDiff("a,b,c,d,f", "a,b,f", Collections.<String> emptyList());
    }

    @Test
    public void testSimpleDiff() throws Exception {
        assertDiff("a,b", "a,b,c", asList("c"));
        assertDiff("a,b", "", Collections.<String> emptyList());
        assertDiff("", "", Collections.<String> emptyList());
        assertDiff("", "a", asList("a"));
        assertDiff("", "a, b", asList("a", "b"));
    }

    @Test
    public void testDiffWithExtraEntriesInMarked() throws IOException {
        assertDiff("a,b", "a,b,c, e, h", asList("c", "e", "h"));
        assertDiff("a,b,d,e", "a,b,c", asList("c"));
        assertDiff("a,b,d,e,f", "a,b,c,f", asList("c"));
        assertDiff("a,b,d,e,f", "a,b,c,f, h", asList("c", "h"));
        assertDiff("3,7", "2,3,5,9", asList("2", "5", "9"));
    }
    
    @Test
    public void testMarkedDiffWithExtraEntriesInMarked() throws IOException {
        assertReverseDiff("a,b,c,e,h", "a,b,c", asList("e", "h"));
        assertReverseDiff("a,b,d,e", "a,b,c", asList("d", "e"));
        assertReverseDiff("a,b,d", "a,b,d", Collections.<String>emptyList());
        assertReverseDiff("a,0xb,d,e,f", "a,d", asList("0xb", "e", "f"));
        assertReverseDiff("a,0xb,d,e,f", "a,d,e,f,g", asList("0xb"));
    }

    @Test
    public void testDiffLineBreakChars() throws IOException {
        List<String> all = getLineBreakStrings();
        List<String> marked = getLineBreakStrings();
        remove(marked, 3, 2);

        // without escaping, the line breaks will be resolved
        assertDiff(Joiner.on(",").join(marked), Joiner.on(",").join(all),
            asList("/a", "c", "/a/b"));
    }

    @Test
    public void testDiffEscapedLineBreakChars() throws IOException {
        // Escaped characters
        List<String> all = escape(getLineBreakStrings());
        List<String> marked = escape(getLineBreakStrings());
        List<String> diff = remove(marked, 3, 2);

        assertDiff(Joiner.on(",").join(marked), Joiner.on(",").join(all), diff);
    }

    @Test
    public void testDiffTransform() throws IOException {
        assertTransformed("a:x,b:y", "a:1,b:2,c:3,e:4,h", asList("c:3", "e:4", "h"));
        assertTransformed("a,b,d,e", "a,b,c", asList("c"));
        assertTransformed("a:1,b:2,d:3,e:4,f:5", "a:z,b:y,c:x,f:w", asList("c:x"));
        assertTransformed("a,b,d,e,f", "a,b,c,f,h", asList("c", "h"));
        assertTransformed("3:1,7:6", "2:0,3:6,5:3,9:1", asList("2:0", "5:3", "9:1"));
        assertTransformed("", "", Collections.<String> emptyList());
        assertTransformed("", "a, b", asList("a", "b"));
        assertTransformed("", "a:4, b:1", asList("a:4", "b:1"));
    }

    private static List<String> getLineBreakStrings() {
        return Lists.newArrayList("ab\nc\r", "ab\\z", "a\\\\z\nc",
            "/a", "/a/b\nc", "/a/b\rd", "/a/b\r\ne", "/a/c");
    }

    private static List<String> remove(List<String> list, int idx, int count) {
        List<String> diff = Lists.newArrayList();
        int i = 0;
        while (i < count) {
            diff.add(list.remove(idx));
            i++;
        }
        return diff;
    }

    private static List<String> escape(List<String> list) {
        List<String> escaped = Lists.newArrayList();
        for (String s : list) {
            escaped.add(escapeLineBreak(s));
        }
        return escaped;
    }

    private static void assertReverseDiff(String marked, String all, List<String> diff) throws IOException {
        Iterator<String> itr = createItr(all, marked);
        assertThat("marked: " + marked + " all: " + all, ImmutableList.copyOf(itr), is(diff));
    }

    private static void assertDiff(String marked, String all, List<String> diff) throws IOException {
        Iterator<String> itr = createItr(marked, all);
        assertThat("marked: " + marked + " all: " + all, ImmutableList.copyOf(itr), is(diff));
    }

    private static Iterator<String> createItr(String marked, String all) throws IOException {
        return new FileLineDifferenceIterator(lineItr(marked), lineItr(all));
    }

    private static LineIterator lineItr(String seq) {
        Iterable<String> seqItr = Splitter.on(',').trimResults().split(seq);
        String lines = Joiner.on(StandardSystemProperty.LINE_SEPARATOR.value()).join(seqItr);
        return new LineIterator(new StringReader(lines));
    }

    private static void assertTransformed(String marked, String all, List<String> diff) throws IOException {
        Iterator<String> itr = new FileLineDifferenceIterator(lineItr(marked), lineItr(all),
            new Function<String, String>() {
                @Nullable @Override
                public String apply(@Nullable String input) {
                    if (input != null) {
                        return input.split(":")[0];
                    }
                    return null;
                }
            });

        assertThat("marked: " + marked + " all: " + all, ImmutableList.copyOf(itr), is(diff));
    }
}
