package com.welovecoding.netbeans.plugin.editorconfig.processor.operation;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
import javax.swing.text.BadLocationException;
import javax.swing.text.StyledDocument;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
import org.netbeans.api.editor.settings.SimpleValueNames;
import org.netbeans.modules.editor.indent.api.Reformat;
import org.netbeans.modules.editor.indent.spi.CodeStylePreferences;
import org.openide.cookies.EditorCookie;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataObject;
import org.openide.text.NbDocument;
import org.openide.util.Exceptions;
import org.openide.util.Utilities;

public class IndentSizeOperationTest {

  private DataObject dataObject;
  private File file;

  @Before
  public void setUp() {
    String codeWith4SpacesIndent = "(function(){" + System.lineSeparator();
    codeWith4SpacesIndent += "    alert('Hello World!');" + System.lineSeparator();
    codeWith4SpacesIndent += "})();";

    try {
      file = File.createTempFile(this.getClass().getSimpleName(), ".js");
      Path path = Paths.get(Utilities.toURI(file));
      Files.write(path, codeWith4SpacesIndent.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE);
      dataObject = DataObject.find(FileUtil.toFileObject(file));
    } catch (IOException ex) {
      Exceptions.printStackTrace(ex);
    }
  }

  @After
  public void tearDown() {
    file.delete();
  }

  public IndentSizeOperationTest() {
  }

  @Test
  public void itDetectsIfChangesAreNeeded() throws
          IOException, BadLocationException, BackingStoreException {
    String codeWith2SpacesIndent = "(function(){" + System.lineSeparator();
    codeWith2SpacesIndent += "  alert('Hello World!');" + System.lineSeparator();
    codeWith2SpacesIndent += "})();";

    Preferences codeStyle = CodeStylePreferences.get(
            dataObject.getPrimaryFile(),
            dataObject.getPrimaryFile().getMIMEType()
    ).getPreferences();

    // Check indent size before change
    int indentSizeBefore = codeStyle.getInt(SimpleValueNames.INDENT_SHIFT_WIDTH, -1);
    assertEquals(-1, indentSizeBefore);

    // Change indent size within an operation
    boolean changeNeeded = new IndentSizeOperation().run(dataObject.getPrimaryFile(), 2);

    // Save the new style
    codeStyle.flush();

    // Save indent size
    EditorCookie cookie = dataObject.getLookup().lookup(EditorCookie.class);
    cookie.open();

    StyledDocument document = cookie.openDocument();

    NbDocument.runAtomicAsUser(document, () -> {
      try {
        // Save test file
        cookie.saveDocument();

        // Reformat test file
        Reformat reformat = Reformat.get(document);
        reformat.lock();

        try {
          reformat.reformat(0, document.getLength());
        } catch (BadLocationException ex) {
          Exceptions.printStackTrace(ex);
        } finally {
          reformat.unlock();
          try {
            // Save formatted document
            cookie.saveDocument();
            System.out.println("Content saved:");
            System.out.println(document.getText(0, document.getLength()));
          } catch (IOException | BadLocationException ex) {
            Exceptions.printStackTrace(ex);
          }
        }
      } catch (IOException ex) {
        Exceptions.printStackTrace(ex);
      }
    });

    // Update reference to changed code style
    codeStyle = CodeStylePreferences.get(
            dataObject.getPrimaryFile(),
            dataObject.getPrimaryFile().getMIMEType()
    ).getPreferences();
    int indentSizeAfter = codeStyle.getInt(SimpleValueNames.INDENT_SHIFT_WIDTH, -1);

    assertEquals(true, changeNeeded);
    assertEquals(2, indentSizeAfter);

    // TODO: This check fails
    // assertEquals(codeWith2SpacesIndent, dataObject.getPrimaryFile().asText());
  }

}

@@ -2057,24 +2057,52 @@
 xception %7B%0D%0A
+    int indentWidth = 2;%0D%0A%0D%0A
     String c
@@ -2776,62 +2776,497 @@
 (), 
-2);%0D%0A%0D%0A    // Save the new style%0D%0A    codeStyle.flush(
+indentWidth);%0D%0A    assertEquals(true, changeNeeded);%0D%0A%0D%0A    // Update code style reference%0D%0A    codeStyle = CodeStylePreferences.get(%0D%0A            dataObject.getPrimaryFile(),%0D%0A            dataObject.getPrimaryFile().getMIMEType()%0D%0A    ).getPreferences();%0D%0A%0D%0A    // Save the new style%0D%0A    codeStyle.flush();%0D%0A%0D%0A    // Udate reference to changed code style%0D%0A    int indentSizeAfter = codeStyle.getInt(SimpleValueNames.INDENT_SHIFT_WIDTH, -1);%0D%0A    assertEquals(indentWidth, indentSizeAfter
 );%0D%0A
@@ -4342,388 +4342,8 @@
 %0D%0A%0D%0A
-    // Update reference to changed code style%0D%0A    codeStyle = CodeStylePreferences.get(%0D%0A            dataObject.getPrimaryFile(),%0D%0A            dataObject.getPrimaryFile().getMIMEType()%0D%0A    ).getPreferences();%0D%0A    int indentSizeAfter = codeStyle.getInt(SimpleValueNames.INDENT_SHIFT_WIDTH, -1);%0D%0A%0D%0A    assertEquals(true, changeNeeded);%0D%0A    assertEquals(2, indentSizeAfter);%0D%0A%0D%0A
     
@@ -4372,19 +4372,16 @@
 ils%0D%0A   
- //
  assertE

Test fails because spaces are not changed.