/*
 * Copyright 2011 Henry Coles
 *
 * 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 org.pitest.mutationtest.tooling;

import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;

import java.io.IOException;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.Optional;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

public class DirectorySourceLocatorTest {

  @Rule
  public TemporaryFolder folder = new TemporaryFolder();
  Path root;

  private DirectorySourceLocator testee;

  @Before
  public void setUp() {
    root = folder.getRoot().toPath();
    this.testee = new DirectorySourceLocator(this.root, StandardCharsets.UTF_8);
  }

  @Test
  public void locatesSourceForClassesInDefaultPackage() throws Exception {
    createFile(root.resolve("Foo.java"), "foo");
    createFile(root.resolve("Bar.java"), "bar");
    Optional<Reader> actual = testee.locate(singletonList("Foo"), "Foo.java");
    assertThat(actual).isPresent();
    assertThat(content(actual)).isEqualTo("foo");
  }

  @Test
  public void locatesSourceForClassesInNamedPackages()  throws Exception  {
    createFile(root.resolve("com/example/Foo.java"), "foo");
    createFile(root.resolve("com/example/Bar.java"), "bar");
    Optional<Reader> actual = testee.locate(singletonList("com.example.Foo"), "Foo.java");
    assertThat(content(actual)).isEqualTo("foo");
  }

  @Test
  public void findsFileInPackageBeforeOneAtRoot()  throws Exception  {
    createFile(root.resolve("com/example/Foo.java"), "this one");
    createFile(root.resolve("Foo.java"), "not this one");
    Optional<Reader> actual = testee.locate(singletonList("com.example.Foo"), "Foo.java");
    assertThat(content(actual)).isEqualTo("this one");
  }

  @Test
  public void findsFileInRootBeforeOneInWrongPackage()  throws Exception  {
    createFile(root.resolve("com/example/other/Foo.java"), "not this one");
    createFile(root.resolve("Foo.java"), "this one");
    Optional<Reader> actual = testee.locate(singletonList("com.example.Foo"), "Foo.java");
    assertThat(content(actual)).isEqualTo("this one");
  }

  @Test
  public void usesFileInRightPAckage()  throws Exception  {
    createFile(root.resolve("com/example/other/Foo.java"), "not this one");
    createFile(root.resolve("com/example/correct/Foo.java"), "this one");
    Optional<Reader> actual = testee.locate(singletonList("com.example.correct.Foo"), "Foo.java");
    assertThat(content(actual)).isEqualTo("this one");
  }

  @Test
  public void doesNotTryToReadDirectories()  throws Exception  {
    Files.createDirectories(root.resolve("com/example/Foo.java"));
    createFile(root.resolve("Foo.java"), "this one");
    Optional<Reader> actual = testee.locate(singletonList("com.example.Foo"), "Foo.java");
    assertThat(content(actual)).isEqualTo("this one");
  }

  @Test
  public void doesNotErrorWhenRootDoesNotExist() {
    testee = new DirectorySourceLocator(this.root.resolve("doesNotExist"), StandardCharsets.UTF_8);
    assertThatCode(() -> testee.locate(singletonList("com"), "Bar.java"))
            .doesNotThrowAnyException();
  }

  private void createFile(Path file, String content) throws IOException {
    if (file.getParent() != null) {
      Files.createDirectories(file.getParent());
    }

    Files.write(file, content.getBytes(StandardCharsets.UTF_8));
  }

  private String content(Optional<Reader> reader) throws Exception {
    if (reader.isPresent()) {
      return content(reader.get());
    }
    return "";
  }

  private String content(Reader reader) throws Exception {
    String s = "";
    int ch;
    while ((ch = reader.read()) != -1) {
      s += (char) ch;
    }
    reader.close();
    return s;
  }
}

@@ -947,38 +947,8 @@
 th;%0A
-import java.util.Collections;%0A
 impo
@@ -2454,32 +2454,649 @@
 his one%22);%0A  %7D%0A%0A
+  @Test%0A  public void findsFileInCorrectPackageBeforeWronglyPackagedOnes()  throws Exception  %7B%0A    createFile(root.resolve(%22com/example/correct/Foo.java%22), %22this one%22);%0A    createFile(root.resolve(%22Foo.java%22), %22not this one%22);%0A    createFile(root.resolve(%22com/example/Foo.java%22), %22not this one%22);%0A    createFile(root.resolve(%22com/example/wrong/Foo.java%22), %22not this one%22);%0A    createFile(root.resolve(%22com/example/correct/wrong/Foo.java%22), %22not this one%22);%0A    Optional%3CReader%3E actual = testee.locate(singletonList(%22com.example.correct.Foo%22), %22Foo.java%22);%0A    assertThat(content(actual)).isEqualTo(%22this one%22);%0A  %7D%0A%0A
   @Test%0A  public

check uses file from correct package