package com.zoox.graphBoardProroBuilder;

import static org.junit.Assert.assertEquals;

import com.zoox.graphBoardProtoBuilder.GraphBoardNode;

import org.junit.Test;

public class GraphBoardNodeTest {
  public static final String SINGLE_NODE_1 = 
  "node {" +
  "\n\tname: node1" +
  "\n\top: \"???\"" +
  "\n\tinclude: \"EXCLUDE\"" +
  "\n}";

  public static final String SINGLE_NODE_2 = 
  "node {" +
  "\n\tname: node2" +
  "\n\top: \"???\"" +
  "\n\tinclude: \"EXCLUDE\"" +
  "\n}";

  public static final String SINGLE_NODE_3 = 
  "node {" +
  "\n\tname: node3" +
  "\n\top: \"???\"" +
  "\n\tinclude: \"EXCLUDE\"" +
  "\n}";

  public static final String IN_NODE_1 = 
  "node {" +
  "\n\tname: node1" +
  "\n\top: \"???\"" +
  "\n\tinput: \"node2\"" +
  "\n\tinclude: \"EXCLUDE\"" +
  "\n}";

  public static final String IN_NODE_2 =
  "node {" +
  "\n\tname: node2" +
  "\n\top: \"???\"" +
  "\n\tinput: \"node1\"" +
  "\n\tinclude: \"EXCLUDE\"" +
  "\n}";

  public static final String IN_NODE_3 = 
  "node {" +
  "\n\tname: node3" +
  "\n\top: \"???\"" +
  "\n\tinput: \"node1\"" +
  "\n\tinclude: \"EXCLUDE\"" +
  "\n}";

  public static final String CIRCULAR_NODE_1 = 
  "node {" +
  "\n\tname: node1" +
  "\n\top: \"???\"" +
  "\n\tinput: \"node3\"" +
  "\n\tinclude: \"EXCLUDE\"" +
  "\n}";

  public static final String CIRCULAR_NODE_2 = IN_NODE_2;

  public static final String CIRCULAR_NODE_3 = 
  "node {" +
  "\n\tname: node3" +
  "\n\top: \"???\"" +
  "\n\tinput: \"node2\"" +
  "\n\tinclude: \"EXCLUDE\"" +
  "\n}";

  public static final String DOUBLE_CIRCULAR_NODE_1 =
  "node {" +
  "\n\tname: node1" +
  "\n\top: \"???\"" +
  "\n\tinput: \"node2\"" +
  "\n\tinput: \"node3\"" +
  "\n\tinclude: \"INCLUDE\"" +
  "\n}";

  public static final String DOUBLE_CIRCULAR_NODE_2 =
  "node {" +
  "\n\tname: node2" +
  "\n\top: \"???\"" +
  "\n\tinput: \"node1\"" +
  "\n\tinput: \"node3\"" +
  "\n\tinclude: \"INCLUDE\"" +
  "\n}";

  public static final String DOUBLE_CIRCULAR_NODE_3 =
  "node {" +
  "\n\tname: node3" +
  "\n\top: \"???\"" +
  "\n\tinput: \"node1\"" +
  "\n\tinput: \"node2\"" +
  "\n\tinclude: \"INCLUDE\"" +
  "\n}";

  @Test
  public void emptyGraphBoardNode()
  {
    GraphBoardNode node1 = new GraphBoardNode("node1");
    assertEquals(SINGLE_NODE_1, node1.toString());
  }

  @Test
  public void singleConnection()
  {
    GraphBoardNode node1 = new GraphBoardNode("node1");
    GraphBoardNode node2 = new GraphBoardNode("node2");
    node2.addInNode(node1);
    assertEquals(SINGLE_NODE_1, node1.toString());
    assertEquals(IN_NODE_2, node2.toString());
  }

  @Test
  public void addNodeTwiceConnection()
  {
    GraphBoardNode node1 = new GraphBoardNode("node1");
    GraphBoardNode node2 = new GraphBoardNode("node2");
    node2.addInNode(node1);
    node2.addInNode(node1);
    assertEquals(SINGLE_NODE_1, node1.toString());
    assertEquals(IN_NODE_2, node2.toString());
  }

  @Test
  public void doubleConnection()
  {
    GraphBoardNode node1 = new GraphBoardNode("node1");
    GraphBoardNode node2 = new GraphBoardNode("node2");
    node1.addInNode(node2);
    node2.addInNode(node1);
    assertEquals(IN_NODE_1, node1.toString());
    assertEquals(IN_NODE_2, node2.toString());
  }

  @Test
  public void circularSingleConnection()
  {
    GraphBoardNode node1 = new GraphBoardNode("node1");
    GraphBoardNode node2 = new GraphBoardNode("node2");
    GraphBoardNode node3 = new GraphBoardNode("node3");
    node1.addInNode(node3);
    node2.addInNode(node1);
    node3.addInNode(node2);
    assertEquals(CIRCULAR_NODE_1, node1.toString());
    assertEquals(CIRCULAR_NODE_2, node2.toString());
    assertEquals(CIRCULAR_NODE_3, node3.toString());
  }

  @Test
  public void doubleCircularConnection() //testing INCLUDE vs EXCLUDE
  {
    GraphBoardNode node1 = new GraphBoardNode("node1");
    GraphBoardNode node2 = new GraphBoardNode("node2");
    GraphBoardNode node3 = new GraphBoardNode("node3");
    node1.addInNode(node2);
    node1.addInNode(node3);
    node2.addInNode(node1);
    node2.addInNode(node3);
    node3.addInNode(node1);
    node3.addInNode(node2);
    assertEquals(DOUBLE_CIRCULAR_NODE_1, node1.toString());
    assertEquals(DOUBLE_CIRCULAR_NODE_2, node2.toString());
    assertEquals(DOUBLE_CIRCULAR_NODE_3, node3.toString());
  }

  @Test
  public void testEmptyDisappear()
  {
    GraphBoardNode node1 = new GraphBoardNode("node1");
    node1.disappear();
    assertEquals(SINGLE_NODE_1, node1.toString());
  }

  @Test
  public void testOutDisappear()
  {
    GraphBoardNode node1 = new GraphBoardNode("node1");
    GraphBoardNode node2 = new GraphBoardNode("node2");
    node2.addInNode(node1);
    assertEquals(SINGLE_NODE_1, node1.toString());
    assertEquals(IN_NODE_2, node2.toString());
    node1.disappear();
    assertEquals(SINGLE_NODE_1, node1.toString());
    assertEquals(SINGLE_NODE_2, node2.toString());
  }

  @Test
  public void testInDisappear()
  {
    GraphBoardNode node1 = new GraphBoardNode("node1");
    GraphBoardNode node2 = new GraphBoardNode("node2");
    node2.addInNode(node1);
    assertEquals(SINGLE_NODE_1, node1.toString());
    assertEquals(IN_NODE_2, node2.toString());
    node2.disappear();
    assertEquals(SINGLE_NODE_1, node1.toString());
    assertEquals(SINGLE_NODE_2, node2.toString());
  }

  @Test
  public void testInOutDisappear()
  {
    GraphBoardNode node1 = new GraphBoardNode("node1");
    GraphBoardNode node2 = new GraphBoardNode("node2");
    GraphBoardNode node3 = new GraphBoardNode("node3");
    node2.addInNode(node1);
    node3.addInNode(node2);
    assertEquals(SINGLE_NODE_1, node1.toString());
    assertEquals(CIRCULAR_NODE_2, node2.toString());
    assertEquals(CIRCULAR_NODE_3, node3.toString());
    node2.disappear();
    assertEquals(SINGLE_NODE_1, node1.toString());
    assertEquals(SINGLE_NODE_2, node2.toString());
    assertEquals(IN_NODE_3, node3.toString());
  }

  @Test
  public void testRepeatDisappear()
  {
    GraphBoardNode node1 = new GraphBoardNode("node1");
    GraphBoardNode node2 = new GraphBoardNode("node2");
    GraphBoardNode node3 = new GraphBoardNode("node3");
    node2.addInNode(node1);
    node3.addInNode(node1);
    node3.addInNode(node2);
    
    String node3String =
    "node {" +
    "\n\tname: node3" +
    "\n\top: \"???\"" +
    "\n\tinput: \"node1\"" +
    "\n\tinput: \"node2\"" +
    "\n\tinclude: \"EXCLUDE\"" +
    "\n}";

    assertEquals(SINGLE_NODE_1, node1.toString());
    assertEquals(CIRCULAR_NODE_2, node2.toString());
    assertEquals(node3String, node3.toString());
    node2.disappear();
    node2.disappear();
    assertEquals(SINGLE_NODE_1, node1.toString());
    assertEquals(SINGLE_NODE_2, node2.toString());
    assertEquals(IN_NODE_3, node3.toString());
  }

  @Test
  public void testMultipleDisappear()
  {
    GraphBoardNode node1 = new GraphBoardNode("node1");
    GraphBoardNode node2 = new GraphBoardNode("node2");
    GraphBoardNode node3 = new GraphBoardNode("node3");
    GraphBoardNode node4 = new GraphBoardNode("node4");
    GraphBoardNode node5 = new GraphBoardNode("node5");

    node3.addInNode(node1);
    node3.addInNode(node2);
    node4.addInNode(node3);
    node5.addInNode(node3);

    String node4BeforeString = 
    "node {" +
    "\n\tname: node4" +
    "\n\top: \"???\"" +
    "\n\tinput: \"node3\"" +
    "\n\tinclude: \"EXCLUDE\"" +
    "\n}";

    String node5BeforeString = 
    "node {" +
    "\n\tname: node5" +
    "\n\top: \"???\"" +
    "\n\tinput: \"node3\"" +
    "\n\tinclude: \"EXCLUDE\"" +
    "\n}";

    assertEquals(SINGLE_NODE_1, node1.toString());
    assertEquals(SINGLE_NODE_2, node2.toString());
    assertEquals(DOUBLE_CIRCULAR_NODE_3, node3.toString());
    assertEquals(node4BeforeString, node4.toString());
    assertEquals(node5BeforeString, node5.toString());

    node3.disappear();

    String node4AfterString = 
    "node {" +
    "\n\tname: node4" +
    "\n\top: \"???\"" +
    "\n\tinput: \"node1\"" +
    "\n\tinput: \"node2\"" +
    "\n\tinclude: \"EXCLUDE\"" +
    "\n}";

    String node5AfterString = 
    "node {" +
    "\n\tname: node5" +
    "\n\top: \"???\"" +
    "\n\tinput: \"node1\"" +
    "\n\tinput: \"node2\"" +
    "\n\tinclude: \"EXCLUDE\"" +
    "\n}";

    assertEquals(SINGLE_NODE_1, node1.toString());
    assertEquals(SINGLE_NODE_2, node2.toString());
    assertEquals(SINGLE_NODE_3, node3.toString());
    assertEquals(node4AfterString, node4.toString());
    assertEquals(node5AfterString, node5.toString());
  }  
}