package com.jetbrains.jsonSchema.impl;

import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.util.concurrency.Semaphore;
import org.junit.Assert;
import org.junit.Test;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @author Irina.Chernushina on 8/29/2015.
 */
public class JsonSchemaReadTest {
  @org.junit.Test
  public void testReadSchemaItself() throws Exception {
    final File file = new File(PlatformTestUtil.getCommunityPath(), "json/tests/testData/jsonSchema/schema.json");
    Assert.assertTrue(file.exists());
    final JsonSchemaReader reader = new JsonSchemaReader();
    final JsonSchemaObject read = reader.read(new FileReader(file));

    Assert.assertEquals("http://json-schema.org/draft-04/schema#", read.getId());
    Assert.assertTrue(read.getDefinitions().containsKey("positiveInteger"));
    Assert.assertTrue(read.getProperties().containsKey("multipleOf"));
    Assert.assertTrue(read.getProperties().containsKey("type"));
    Assert.assertTrue(read.getProperties().containsKey("additionalProperties"));
    Assert.assertEquals(2, read.getProperties().get("additionalItems").getAnyOf().size());
    Assert.assertEquals("#", read.getProperties().get("additionalItems").getAnyOf().get(1).getRef());

    final JsonSchemaObject required = read.getProperties().get("required");
    Assert.assertEquals(JsonSchemaType._array, required.getType());
    Assert.assertEquals(1, required.getMinItems().intValue());
    Assert.assertEquals(JsonSchemaType._string, required.getItemsSchema().getType());

    final JsonSchemaObject minLength = read.getProperties().get("minLength");
    Assert.assertNotNull(minLength.getAllOf());
    final List<JsonSchemaObject> minLengthAllOf = minLength.getAllOf();
    boolean haveIntegerType = false;
    Integer defaultValue = null;
    Integer minValue = null;
    for (JsonSchemaObject object : minLengthAllOf) {
      haveIntegerType |= JsonSchemaType._integer.equals(object.getType());
      if (object.getDefault() instanceof  Number) {
        defaultValue = ((Number)object.getDefault()).intValue();
      }
      if (object.getMinimum() != null) {
        minValue = object.getMinimum().intValue();
      }
    }
    Assert.assertTrue(haveIntegerType);
    Assert.assertEquals(0, defaultValue.intValue());
    Assert.assertEquals(0, minValue.intValue());
  }

  @Test
  public void testReadSchemaWithCustomTags() throws Exception {
    final File file = new File(PlatformTestUtil.getCommunityPath(), "json/tests/testData/jsonSchema/withNotesCustomTag.json");
    Assert.assertTrue(file.exists());
    final JsonSchemaReader reader = new JsonSchemaReader();
    final JsonSchemaObject read = reader.read(new FileReader(file));
    Assert.assertTrue(read.getDefinitions().get("common").getProperties().containsKey("id"));
  }

  @Test
  public void testReadSchemaWithWrongRequired() throws Exception {
    testSchemaReadNotHung(new File(PlatformTestUtil.getCommunityPath(), "json/tests/testData/jsonSchema/withWrongRequired.json"));
  }

  @Test
  public void testReadSchemaWithWrongItems() throws Exception {
    testSchemaReadNotHung(new File(PlatformTestUtil.getCommunityPath(), "json/tests/testData/jsonSchema/withWrongItems.json"));
  }

  private static void testSchemaReadNotHung(final File file) throws IOException {
    Assert.assertTrue(file.exists());

    final AtomicBoolean done = new AtomicBoolean();
    final AtomicReference<IOException> error = new AtomicReference<>();
    final Semaphore semaphore = new Semaphore();
    semaphore.down();
    new Thread(new Runnable() {
      @Override
      public void run() {
        final JsonSchemaReader reader = new JsonSchemaReader();
        try {
          reader.read(new FileReader(file));
          done.set(true);
        }
        catch (IOException e) {
          error.set(e);
        } finally {
          semaphore.up();
        }
      }
    }, "read test json schema " + file.getName()).start();
    semaphore.waitFor(TimeUnit.SECONDS.toMillis(60));
    if (error.get() != null) throw error.get();
    Assert.assertTrue("Reading test schema hung!", done.get());
  }
}

@@ -3167,33 +3167,33 @@
 Data/jsonSchema/
-w
+W
 ithWrongRequired
@@ -3383,17 +3383,17 @@
 nSchema/
-w
+W
 ithWrong
@@ -3490,24 +3490,117 @@
 Exception %7B%0A
+    // because of threading%0A    if (Runtime.getRuntime().availableProcessors() %3C 2) return;%0A%0A
     Assert.a
@@ -3824,16 +3824,38 @@
 n();%0A   
+ final Thread thread =
  new Thr
@@ -4141,16 +4141,24 @@
        %7D
+%0A       
  finally
@@ -4253,16 +4253,40 @@
 tName())
+;%0A    try %7B%0A      thread
 .start()
@@ -4283,24 +4283,26 @@
 ad.start();%0A
+  
     semaphor
@@ -4341,14 +4341,17 @@
 lis(
-6
+12
 0));%0A
+  
     
@@ -4394,24 +4394,26 @@
 .get();%0A    
+  
 Assert.asser
@@ -4456,18 +4456,66 @@
 one.get());%0A
+    %7D finally %7B%0A      thread.interrupt();%0A    %7D%0A
   %7D%0A%7D%0A

fix test, sorry (filenames letters case) + always kill the second thread