// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

package com.yahoo.vespa.hosted.node.admin.task.util.file;

import com.yahoo.vespa.hosted.node.admin.component.TaskContext;
import com.yahoo.vespa.test.file.TestFileSystem;
import org.junit.Test;
import org.mockito.ArgumentCaptor;

import java.nio.file.FileSystem;
import java.util.Collections;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

public class EditorTest {
    private final FileSystem fileSystem = TestFileSystem.create();
    private final UnixPath path = new UnixPath(fileSystem.getPath("/file"));

    @Test
    public void testEdit() {
        path.writeUtf8File("first\n" +
                "second\n" +
                "third\n");

        LineEditor lineEditor = mock(LineEditor.class);
        when(lineEditor.edit(any())).thenReturn(
                LineEdit.none(), // don't edit the first line
                LineEdit.remove(), // remove the second
                LineEdit.replaceWith("replacement")); // replace the third

        Editor editor = new Editor(path.toPath(), lineEditor);
        TaskContext context = mock(TaskContext.class);

        assertTrue(editor.converge(context));

        verify(lineEditor, times(3)).edit(any());

        // Verify the system modification message
        ArgumentCaptor<String> modificationMessage = ArgumentCaptor.forClass(String.class);
        verify(context).recordSystemModification(any(), modificationMessage.capture());
        assertEquals(
                "Patching file /file:\n-second\n-third\n+replacement\n",
                modificationMessage.getValue());

        // Verify the new contents of the file:
        assertEquals("first\n" +
                "replacement\n", path.readUtf8File());
    }

    @Test
    public void testInsert() {
        path.writeUtf8File("second\neight\nfifth\nseventh\n");

        LineEditor lineEditor = mock(LineEditor.class);
        when(lineEditor.edit(any())).thenReturn(
                LineEdit.insertBefore("first"), // insert first, and keep the second line
                LineEdit.replaceWith("third", "fourth"), // remove eight, and replace with third and fourth instead
                LineEdit.none(), // Keep fifth
                LineEdit.insert(Collections.singletonList("sixth"), // insert sixth before seventh
                        Collections.singletonList("eight"))); // add eight after seventh

        Editor editor = new Editor(path.toPath(), lineEditor);
        TaskContext context = mock(TaskContext.class);

        assertTrue(editor.converge(context));

        // Verify the system modification message
        ArgumentCaptor<String> modificationMessage = ArgumentCaptor.forClass(String.class);
        verify(context).recordSystemModification(any(), modificationMessage.capture());
        assertEquals(
                "Patching file /file:\n+" +
                        "first\n" +
                        "-eight\n" +
                        "+third\n" +
                        "+fourth\n" +
                        "+sixth\n" +
                        "+eight\n",
                modificationMessage.getValue());

        // Verify the new contents of the file:
        assertEquals("first\nsecond\nthird\nfourth\nfifth\nsixth\nseventh\neight\n", path.readUtf8File());
    }

    @Test
    public void noop() {
        path.writeUtf8File("line\n");

        LineEditor lineEditor = mock(LineEditor.class);
        when(lineEditor.edit(any())).thenReturn(LineEdit.none());

        Editor editor = new Editor(path.toPath(), lineEditor);
        TaskContext context = mock(TaskContext.class);

        assertFalse(editor.converge(context));

        verify(lineEditor, times(1)).edit(any());

        // Verify the system modification message
        verify(context, times(0)).recordSystemModification(any(), any());

        // Verify same contents
        assertEquals("line\n", path.readUtf8File());
    }
}
@@ -985,74 +985,45 @@
 ile(
-%22first%5Cn%22 +%0A                %22second%5Cn%22 +%0A               
+joinLines(%22first%22, %22second%22,
  %22third
-%5Cn
 %22
+)
 );%0A%0A
@@ -1986,35 +1986,26 @@
 als(
-%22first%5Cn%22 +%0A               
+joinLines(%22first%22,
  %22re
@@ -2013,19 +2013,18 @@
 lacement
-%5Cn
 %22
+)
 , path.r
@@ -2118,41 +2118,56 @@
 ile(
+joinLines(
 %22second
-%5Cn
+%22, %22
 eight
-%5Cn
+%22, %22
 fifth
-%5Cn
+%22, %22
 seventh
-%5Cn
 %22
+)
 );%0A%0A
@@ -3170,17 +3170,16 @@
 /file:%5Cn
-+
 %22 +%0A    
@@ -3199,16 +3199,17 @@
        %22
++
 first%5Cn%22
@@ -3519,71 +3519,110 @@
 als(
+joinLines(
 %22first
-%5Cn
+%22, %22
 second
-%5Cn
+%22, %22
 third
-%5Cn
+%22, %22
 fourth
-%5Cn
+%22, %22
 fifth
-%5Cn
+%22, %22
 sixth
-%5Cn
+%22, %22
 seventh
-%5Cn
+%22, %22
 eight
-%5Cn%22,
+%22),%0A               
  pat
@@ -4278,9 +4278,120 @@
 ;%0A    %7D%0A
+%0A%0A    private static String joinLines(String... lines) %7B%0A        return String.join(%22%5Cn%22, lines) + %22%5Cn%22;%0A    %7D%0A
 %7D

Simplify lines generation in test