package com.github.gquintana.beepbeep.script;

import com.github.gquintana.beepbeep.TestConsumer;
import com.github.gquintana.beepbeep.TestFiles;
import com.github.gquintana.beepbeep.config.ConfigurationException;
import com.github.gquintana.beepbeep.pipeline.ScriptStartEvent;
import org.junit.Test;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;

public class ScriptScannersTest {

    private String readAsString(Script script) throws IOException {
        try (InputStream inputStream = script.getStream();
             ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            TestFiles.copy(inputStream, outputStream);
            return new String(outputStream.toByteArray(), "UTF-8");
        }
    }

    @Test
    public void testResource_Class() throws Exception {
        // Given
        TestConsumer<ScriptStartEvent> output = new TestConsumer<>();
        // When
        String resourceFullName = TestFiles.getResourceFullName("sql/clean/drop.sql");
        SingleScriptScanner scanner = ScriptScanners.resource(TestFiles.class, "sql/clean/drop.sql", output);
        scanner.scan();
        // Then
        assertThat(output.events).hasSize(1);
        ScriptStartEvent event = output.events(ScriptStartEvent.class).get(0);
        assertThat(event.getScript().getFullName()).isEqualTo(resourceFullName);
        assertThat(readAsString(event.getScript()).trim()).isEqualTo("DROP TABLE person;");
    }

    @Test
    public void testResource_ClassLoader() throws Exception {
        // Given
        TestConsumer<ScriptStartEvent> output = new TestConsumer<>();
        // When
        String resourceFullName = TestFiles.getResourceFullName("sql/clean/drop.sql");
        SingleScriptScanner scanner = ScriptScanners.resource(Thread.currentThread().getContextClassLoader(), resourceFullName, output);
        scanner.scan();
        // Then
        assertThat(output.events).hasSize(1);
        ScriptStartEvent event = output.events(ScriptStartEvent.class).get(0);
        assertThat(event.getScript().getFullName()).isEqualTo(resourceFullName);
        assertThat(readAsString(event.getScript()).trim()).isEqualTo("DROP TABLE person;");
    }


    @Test
    public void testAuto_Raw() throws Exception {
        // Given
        TestConsumer<ScriptStartEvent> output = new TestConsumer<>();
        // When
        String resourceFullName = TestFiles.adaptFileSeparator("target/test-classes/" + TestFiles.getResourceFullName("sql/clean/drop.sql"));
        ScriptScanner scanner = ScriptScanners.schemes(resourceFullName, output);
        scanner.scan();
        // Then
        assertThat(output.events).hasSize(1);
        ScriptStartEvent event = output.events(ScriptStartEvent.class).get(0);
        assertThat(event.getScript().getFullName()).isEqualTo(resourceFullName);
    }

    @Test
    public void testAuto_File() throws Exception {
        // Given
        TestConsumer<ScriptStartEvent> output = new TestConsumer<>();
        // When
        String resourceFullName = "target/test-classes/" + TestFiles.getResourceFullName("sql/clean/drop.sql");
        ScriptScanner scanner = ScriptScanners.schemes("file:" + resourceFullName, output);
        scanner.scan();
        // Then
        assertThat(output.events).hasSize(1);
        ScriptStartEvent event = output.events(ScriptStartEvent.class).get(0);
        assertThat(event.getScript().getFullName()).isEqualTo(resourceFullName);
    }

    @Test
    public void testAuto_Class() throws Exception {
        // Given
        TestConsumer<ScriptStartEvent> output = new TestConsumer<>();
        // When
        String resourceFullName = TestFiles.getResourceFullName("sql/clean/drop.sql");
        ScriptScanner scanner = ScriptScanners.schemes("classpath:" + resourceFullName, output);
        scanner.scan();
        // Then
        assertThat(output.events).hasSize(1);
        ScriptStartEvent event = output.events(ScriptStartEvent.class).get(0);
        assertThat(event.getScript().getFullName()).isEqualTo(resourceFullName);
    }

    @Test
    public void testAutos_Raw() throws Exception {
        // Given
        TestConsumer<ScriptStartEvent> output = new TestConsumer<>();
        // When
        String resourceFullName = TestFiles.adaptFileSeparator("target/test-classes/" + TestFiles.getResourceFullName("sql/init/*.sql"));
        ScriptScanner scanner = ScriptScanners.schemes(resourceFullName, output);
        scanner.scan();
        // Then
        assertThat(output.events).hasSize(2);
    }

    @Test
    public void testAutos_Class() throws Exception {
        // Given
        TestConsumer<ScriptStartEvent> output = new TestConsumer<>();
        // When
        String resourceFullName = TestFiles.getResourceFullName("sql/init/*.sql");
        ScriptScanner scanner = ScriptScanners.schemes("classpath:" + resourceFullName, output);
        scanner.scan();
        // Then
        assertThat(output.events).hasSize(2);
    }

    @Test
    public void testAutos_File() throws Exception {
        // Given
        TestConsumer<ScriptStartEvent> output = new TestConsumer<>();
        // When
        String resourceFullName = "target/test-classes/" + TestFiles.getResourceFullName("sql/init/*.sql");
        ScriptScanner scanner = ScriptScanners.schemes("file:" + resourceFullName, output);
        scanner.scan();
        // Then
        assertThat(output.events).hasSize(2);
    }

    @Test
    public void testAuto_Invalidscheme() throws Exception {
        // Given
        TestConsumer<ScriptStartEvent> output = new TestConsumer<>();
        // When
        try {
            ScriptScanner scanner = ScriptScanners.schemes("ftp://server/test.sql", output);
            fail("Exception expected");
        } catch (ConfigurationException e) {
        }
        // Then
    }
}

@@ -2370,20 +2370,22 @@
 oid test
-Auto
+Scheme
 _Raw() t
@@ -3012,20 +3012,22 @@
 oid test
-Auto
+Scheme
 _File() 
@@ -3571,32 +3571,61 @@
 me()).isEqualTo(
+TestFiles.adaptFileSeparator(
 resourceFullName
@@ -3617,32 +3617,33 @@
 esourceFullName)
+)
 ;%0A    %7D%0A%0A    @Te
@@ -3665,20 +3665,22 @@
 oid test
-Auto
+Scheme
 _Class()
@@ -4269,20 +4269,22 @@
 oid test
-Auto
+Scheme
 s_Raw() 
@@ -4748,20 +4748,22 @@
 oid test
-Auto
+Scheme
 s_Class(
@@ -5189,20 +5189,22 @@
 oid test
-Auto
+Scheme
 s_File()
@@ -5653,12 +5653,14 @@
 test
-Auto
+Scheme
 _Inv

Fix ScriptScannersTest for Windows