context: using System;
  using System.Windows.Forms;
  using System.IO;
  using System.Collections;
  using System.Drawing;
  using Geometry;
  using Newtonsoft.Json.Linq;
  using Newtonsoft.Json;
  
  namespace MazeEditor
  {
  	/// <summary>
  	/// Summary description for JsonHelper
  	/// </summary>
  	public class JsonHelper
  	{
          public ArrayList mazeWalls = null;
          public ArrayList mazeRobots = null;
          public ArrayList mazeVictims = null;
  
          public ArrayList mazeSpaces = null;
          public MazeGraph mazeGraph = null;
  
          public string worldName;
          public int iWorldTimeout;
  
          public ArrayList mazeNodeNodes = null;
          public ArrayList mazeSpaceNode = null;
          public ArrayList mazeSpaceRobots = null;
  
          public void LoadAll(String filename) 
          {
              JToken tempJObject;
              StreamReader reader = File.OpenText(filename);
              JObject o = (JObject)JToken.ReadFrom(new JsonTextReader(reader));
  
              if (o.TryGetValue("name", out tempJObject))
                  worldName =  o.GetValue("name").ToString();
  
              if (o.TryGetValue("timeout", out tempJObject))
                  iWorldTimeout = (int)o.GetValue("timeout");
  
              mazeWalls = new ArrayList();
              Hashtable mazeWallsById = new Hashtable();
              mazeRobots = new ArrayList();
              mazeVictims = new ArrayList();
  
              mazeSpaces = new ArrayList();
              Hashtable mazeSpacesById = new Hashtable();
              mazeGraph = new MazeGraph();
  
              mazeNodeNodes = new ArrayList();
              mazeSpaceNode = new ArrayList();
              mazeSpaceRobots = new ArrayList();
  
              foreach (JObject jObject in o.GetValue("walls").Children())
              {
                  MazeWall mazeWall = new MazeWall(
                      new Point2D((double)((JObject)jObject.GetValue("from")).GetValue("x") * 100, (double)((JObject)jObject.GetValue("from")).GetValue("y") * 100),
                      new Point2D((double)((JObject)jObject.GetValue("to")).GetValue("x") * 100, (double)((JObject)jObject.GetValue("to")).GetValue("y") * 100),
                      (float)jObject.GetValue("width") * 100,
                      (float)jObject.GetValue("height") * 100,
                      Color.FromArgb(Convert.ToInt32((string)jObject.GetValue("color"), 16)));
                  if (mazeWall.Color.A == 0)
                      mazeWall.Color = Color.LightGray;
                  mazeWall.ID = (string)jObject.GetValue("id");
                  mazeWalls.Add(mazeWall);
                  mazeWallsById.Add((string)jObject.GetValue("id"), mazeWall);
              }
              if (o.GetValue("gates") != null)
              {
                  foreach (JObject jObject in o.GetValue("gates").Children())
                  {
                      MazeWall mazeWall = new MazeWall(
                          new Point2D((double)((JObject)jObject.GetValue("from")).GetValue("x") * 100, (double)((JObject)jObject.GetValue("from")).GetValue("y") * 100),
                          new Point2D((double)((JObject)jObject.GetValue("to")).GetValue("x") * 100, (double)((JObject)jObject.GetValue("to")).GetValue("y") * 100),
                          0, 0, Color.Black);
                      mazeWall.MazeWallType = MazeWallType.gate;
                      string kind = (string)jObject.GetValue("kind");
                      mazeWall.MazeDoorType = (kind == "door" ? MazeGateType.door : (kind == "passage" ? MazeGateType.passage : MazeGateType.doorOneWayFromTo));      //doorOneWayFromTo will be changed later
                      mazeWall.blocked = (double)jObject.GetValue("blocked");
                      mazeWall.ID = (string)jObject.GetValue("id");
                      mazeWalls.Add(mazeWall);
                      mazeWallsById.Add((string)jObject.GetValue("id"), mazeWall);
                  }
              }
              if (o.GetValue("robots") != null)
              {
                  JToken tmp;
                  Point2D? target;
  
                  foreach (JObject jObject in o.GetValue("robots").Children())
                  {
                      if (jObject.TryGetValue("target", out tmp))
                          target = new Point2D((double)((JObject)jObject.GetValue("target")).GetValue("x"), (double)((JObject)jObject.GetValue("target")).GetValue("y"));
                      else
                          target = null;
  
                      MazeRobot mazeRobot = new MazeRobot(
                          (string)jObject.GetValue("type"),
                          (string)jObject.GetValue("id"),
                          new Point2D((double)((JObject)jObject.GetValue("location")).GetValue("x") * 100, (double)((JObject)jObject.GetValue("location")).GetValue("y") * 100),
                          (float)((JObject)jObject.GetValue("location")).GetValue("z") * 100,
                          //new Point2D((double)((JObject)jObject.GetValue("target")).GetValue("x"),(double)((JObject)jObject.GetValue("target")).GetValue("y"))
                         target
  
                          );
                      mazeRobot.ID = (string)jObject.GetValue("id");
                      mazeRobots.Add(mazeRobot);
                  }
              }
              if (o.GetValue("victims") != null)
              {
                  foreach (JObject jObject in o.GetValue("victims").Children())
                  {
                      MazeVictim mazeVictim = new MazeVictim(
                          new Point2D((double)((JObject)jObject.GetValue("position")).GetValue("x") * 100, (double)((JObject)jObject.GetValue("position")).GetValue("y") * 100));
                      mazeVictim.ID = (string)jObject.GetValue("id");
                      mazeVictims.Add(mazeVictim);
                  }
              }
  
  
  
              Hashtable wallsBySpaceId = new Hashtable();
              if (o.GetValue("space-walls") != null)
              {
                  foreach (JObject jObject in o.GetValue("space-walls").Children())
                  {
                      string spaceId = (string)jObject.GetValue("spaceId");
                      string wallId = (string)jObject.GetValue("wallId");
                      if (wallsBySpaceId.ContainsKey(spaceId))
                      {
                          ((ArrayList)wallsBySpaceId[spaceId]).Add(mazeWallsById[wallId]);
                      }
                      else
                      {
                          ArrayList newArrayList = new ArrayList();
                          newArrayList.Add(mazeWallsById[wallId]);
                          wallsBySpaceId[spaceId] = newArrayList;
                      }
                  }
              }
              if (o.GetValue("space-gates") != null)
              {
                  foreach (JObject jObject in o.GetValue("space-gates").Children())
                  {
                      string spaceId = (string)jObject.GetValue("spaceId");
                      string wallId = (string)jObject.GetValue("gateId");
                      if (wallsBySpaceId.ContainsKey(spaceId))
                      {
                          ((ArrayList)wallsBySpaceId[spaceId]).Add(mazeWallsById[wallId]);
                      }
                      else
                      {
                          ArrayList newArrayList = new ArrayList();
                          newArrayList.Add(mazeWallsById[wallId]);
                          wallsBySpaceId[spaceId] = newArrayList;
                      }
                  }
              }
  
              if (o.GetValue("spaces") != null)
              {
                  foreach (JObject jObject in o.GetValue("spaces").Children())
                  {
                      MazeSpace newRoom = new MazeSpace((ArrayList)wallsBySpaceId[(string)jObject.GetValue("id")]);
                      newRoom.ID = (string)jObject.GetValue("id");
                      newRoom.MazeRoomType = (MazeSpaceType)System.Enum.Parse(typeof(MazeSpaceType), (string)jObject.GetValue("kind"));
                      newRoom.Function = (string)jObject.GetValue("function");
                      newRoom.Name = (string)jObject.GetValue("name");
                      newRoom.ExpectedPersonCount = (int)jObject.GetValue("expectedPersonCount");
  
                      if (jObject.TryGetValue("searched", out tempJObject))
                          newRoom.Searched = (int)jObject.GetValue("searched");
                      
                      mazeSpaces.Add(newRoom);
                      mazeSpacesById[newRoom.ID] = newRoom;
  
                      foreach (MazeWall roomWall in newRoom.Walls)
                      {
                          if (roomWall.RoomFrom == null)
                              roomWall.RoomFrom = newRoom;
                          else
                              roomWall.RoomTo = newRoom;
                      }
                  }
              }
  
              ///////////////////////////  graph
  
              Hashtable spacesByNodeId = new Hashtable();
              if (o.GetValue("space-nodes") != null)
              {
                  foreach (JObject jObject in o.GetValue("space-nodes").Children())
                  {
                      spacesByNodeId[(string)jObject.GetValue("nodeId")] = mazeSpacesById[(string)jObject.GetValue("spaceId")];
                  }
              }
              Hashtable gatesByNodeId = new Hashtable();
              if (o.GetValue("gate-nodes") != null)
              {
                  foreach (JObject jObject in o.GetValue("gate-nodes").Children())
                  {
                      gatesByNodeId[(string)jObject.GetValue("nodeId")] = mazeWallsById[(string)jObject.GetValue("gateId")];
                  }
              }
  
              Hashtable nodesById = new Hashtable();
              if (o.GetValue("nodes") != null)
              {
                  foreach (JObject jObject in o.GetValue("nodes").Children())
                  {
                      MazeNode node = new MazeNode(new Point2D((double)((JObject)jObject.GetValue("position")).GetValue("x") * 100, (double)((JObject)jObject.GetValue("position")).GetValue("y") * 100),
                          (MazeSpace)spacesByNodeId[(string)jObject.GetValue("id")],
                          gatesByNodeId[(string)jObject.GetValue("id")] as MazeWall);
                      node.ID = (string)jObject.GetValue("id");
                      nodesById[node.ID] = node;
                      mazeGraph.AddNode(node);
                  }
              }
  
              if (o.GetValue("node-nodes") != null)
              {
                  foreach (JObject jObject in o.GetValue("node-nodes").Children())
                  {
                      MazeNode fromNode = (MazeNode)nodesById[(string)jObject.GetValue("nodeFromId")];
                      MazeNode toNode = (MazeNode)nodesById[(string)jObject.GetValue("nodeToId")];
  
                      if (fromNode.Door != null && (fromNode.Door.MazeDoorType == MazeGateType.doorOneWayFromTo || fromNode.Door.MazeDoorType == MazeGateType.doorOneWayToFrom))
                      {
                          if (fromNode.Room == fromNode.Door.RoomFrom)
                              fromNode.Door.MazeDoorType = MazeGateType.doorOneWayFromTo;
                          else
                              fromNode.Door.MazeDoorType = MazeGateType.doorOneWayToFrom;
                      }
                      mazeGraph.AddArc(fromNode, toNode);
  
                      mazeNodeNodes.Add(new MazeNodeNodes(jObject.GetValue("nodeFromId").ToString(), jObject.GetValue("nodeToId").ToString(), double.Parse(jObject.GetValue("cost").ToString()), double.Parse(jObject.GetValue("blocked").ToString())));
                  }
              }
  
              if (o.GetValue("space-nodes") != null)
              {
                  foreach (JObject jObject in o.GetValue("space-nodes").Children())
                  {
                      mazeSpaceNode.Add(new MazeSpaceNodes(jObject.GetValue("type").ToString(), 
                                                           jObject.GetValue("spaceId").ToString(), 
                                                           jObject.GetValue("nodeId").ToString()));
                  }
              }
  
              if (o.GetValue("space-robots") != null)
              {
                  foreach (JObject jObject in o.GetValue("space-robots").Children())
                  {
                      mazeSpaceRobots.Add(new MazeSpaceRobots(jObject.GetValue("type").ToString(),
                                                           jObject.GetValue("spaceId").ToString(),
                                                           jObject.GetValue("robotId").ToString()));
                  }
              }
  
              
              reader.Close();
          }
  
          public static void SaveAll(String filename, ArrayList mazeWalls, ArrayList mazeRobots, ArrayList mazeVictims, ArrayList mazeRooms, MazeGraph mazeGraph,string sWorldName,int iTimeout)
          {
  
              ArrayList jWalls = new ArrayList();
              ArrayList jGates = new ArrayList(); 
              
  
  
              foreach (MazeWall mazeWall in mazeWalls)
              {
                  if (mazeWall.MazeWallType == MazeWallType.wall)
                  {
                      jWalls.Add(new JObject(
                             new JProperty("type", "wall"),
                             new JProperty("id", mazeWall.ID),
                             new JProperty("width", mazeWall.Width / 100),
                             new JProperty("height", mazeWall.Height / 100),
                             new JProperty("color", mazeWall.Color.ToArgb().ToString("x")),
                             new JProperty("from", new JObject(new JProperty("x", mazeWall.points[0].X / 100), new JProperty("y", mazeWall.points[0].Y / 100))),
                             new JProperty("to", new JObject(new JProperty("x", mazeWall.points[1].X / 100), new JProperty("y", mazeWall.points[1].Y / 100)))));
                  }
                  else
                  {
                       jGates.Add(new JObject(
                            new JProperty("type", "gate"),
                            new JProperty("id", mazeWall.ID),
                            new JProperty("kind", (mazeWall.MazeDoorType == MazeGateType.doorOneWayFromTo || mazeWall.MazeDoorType == MazeGateType.doorOneWayToFrom ? "doorOneWay" : mazeWall.MazeDoorType.ToString())),
                            new JProperty("blocked", mazeWall.blocked),
                            new JProperty("from", new JObject(new JProperty("x", mazeWall.points[0].X / 100), new JProperty("y", mazeWall.points[0].Y / 100))),
                            new JProperty("to", new JObject(new JProperty("x", mazeWall.points[1].X / 100), new JProperty("y", mazeWall.points[1].Y / 100)))));
                  }
              }
  
              ArrayList jRobots = new ArrayList();
              foreach (MazeRobot mazeRobot in mazeRobots)
              {
                  jRobots.Add(new JObject(
                             new JProperty("type", "robot"),
                             new JProperty("id", mazeRobot.ID),
                             new JProperty("kind", mazeRobot.Type),
                             new JProperty("location", new JObject(
                                 new JProperty("x", mazeRobot.position.X / 100),
                                 new JProperty("y", mazeRobot.position.Y / 100),
                                 new JProperty("z", mazeRobot.Height / 100),
  
gt:                                new JProperty("alpha", 0.0001))),