#INCLUDE "json.bi"

FUNCTION JSON_GenerateObject(ArrayMembers() AS JSON_member) AS STRING
  DIM Result AS STRING = CHR(JSON_TOKEN_OBJECT_OPEN) + CHR(JSON_TOKEN_LF)
  FOR i AS ULONG = 0 TO UBOUND(ArrayMembers)
    IF ArrayMembers(i).Name <> "" THEN
      'Add a 2 space indentation
      Result += CHR(JSON_TOKEN_SPACE) + CHR(JSON_TOKEN_SPACE)
      'Add the opening double quote
      Result += CHR(JSON_TOKEN_DOUBLE_QUOTE)
      'Place the name
      Result +=	ArrayMembers(i).Name
      'Add the closing double quote
      Result += CHR(JSON_TOKEN_DOUBLE_QUOTE)
      'Place the colon surounded by whitespaces
      Result += CHR(JSON_TOKEN_SPACE) + CHR(JSON_TOKEN_COLON) + CHR(JSON_TOKEN_SPACE)
      IF ArrayMembers(i).Value.ValueType <> JSON_TYPE_ERROR THEN
        'We want to only add valid JSON values
        Result += ArrayMembers(i).Value.RawContent
      ELSE
        'Instead of adding an erroneus value just place a null
        Result += "null"
      END IF
      IF i < UBOUND(ArrayMembers) THEN
        'Add a mmember separator except for the last one
        Result += CHR(JSON_TOKEN_SPACE) + CHR(JSON_TOKEN_COMMA)
      END IF
      'Add a final newline
      Result += CHR(JSON_TOKEN_LF)
    ELSE
      'Empty member name?, fail gracefully
      EXIT FOR
    END IF
  NEXT
  Result += CHR(JSON_TOKEN_OBJECT_CLOSE)
  JSON_GenerateObject = Result
  Result = ""
END FUNCTION

FUNCTION JSON_GenerateArray (ArrayValues() AS JSON_Value) AS STRING
  DIM Result AS STRING
  Result = CHR(JSON_TOKEN_ARRAY_OPEN) + CHR(JSON_TOKEN_LF)
  FOR i AS ULONG = 0 TO UBOUND(ArrayValues)
    'Add a 2 space indentation
    Result += CHR(JSON_TOKEN_SPACE) + CHR(JSON_TOKEN_SPACE)
    IF ArrayValues(i).ValueType <> JSON_TYPE_ERROR THEN
      'We want to only add valid JSON values
      Result += ArrayValues(i).RawContent
    ELSE
      'Instead of adding an erroneus value just place a null
      Result += "null"
    END IF
    IF i < UBOUND(ArrayValues) THEN
      'Add a value separator except for the last one
      Result += CHR(JSON_TOKEN_SPACE) + CHR(JSON_TOKEN_COMMA)
    END IF
    'Add a final newline
    Result += CHR(JSON_TOKEN_LF)
  NEXT
  Result += CHR(JSON_TOKEN_ARRAY_CLOSE)
  JSON_GenerateArray = Result
  Result = ""
END FUNCTION

FUNCTION JSON_GenerateString (Content AS STRING) AS STRING
  DIM Result AS STRING, Char AS ULONG
  'Add opening double quote
  Result = CHR(JSON_TOKEN_DOUBLE_QUOTE)
  FOR i AS ULONG = 1 TO LEN(Content)
    Char = ASC(MID(Content, i, 1))
    SELECT CASE Char
      CASE JSON_TOKEN_TAB
        Result += CHR(JSON_TOKEN_ESCAPE) + "t"
      CASE JSON_TOKEN_LF
        Result += CHR(JSON_TOKEN_ESCAPE) + "n"
      CASE JSON_TOKEN_CR
        Result += CHR(JSON_TOKEN_ESCAPE) + "r"
      CASE JSON_TOKEN_DOUBLE_QUOTE
        Result += CHR(JSON_TOKEN_ESCAPE) + CHR(JSON_TOKEN_DOUBLE_QUOTE)
      CASE JSON_TOKEN_ESCAPE
        Result += CHR(JSON_TOKEN_ESCAPE) + CHR(JSON_TOKEN_ESCAPE)
      CASE JSON_TOKEN_SLASH
        Result += CHR(JSON_TOKEN_ESCAPE) + CHR(JSON_TOKEN_SLASH)
      CASE JSON_TOKEN_ARRAY_OPEN
        Result += CHR(JSON_TOKEN_ESCAPE) + "u005b"
      CASE JSON_TOKEN_ARRAY_CLOSE
        Result += CHR(JSON_TOKEN_ESCAPE) + "u005d"
      CASE JSON_TOKEN_OBJECT_OPEN
        Result += CHR(JSON_TOKEN_ESCAPE) + "u007b"
      CASE JSON_TOKEN_OBJECT_CLOSE
        Result += CHR(JSON_TOKEN_ESCAPE) + "u007d"
      CASE ELSE
        Result += CHR(Char)
    END SELECT
  NEXT
  Result += CHR(JSON_TOKEN_DOUBLE_QUOTE)
  JSON_GenerateString = Result
  Result = ""
END FUNCTION

SUB JSON_AddMember(oJSON AS JSON_Object, NewMember AS JSON_Member, Index AS UINTEGER = 0)
  DIM AS JSON_Member ArrayOldMembers(oJSON.MemberCount - 1), ArrayNewMembers(oJSON.MemberCount)
  JSON_ParseObject(oJSON, ArrayOldMembers())
  FOR CurPos AS ULONG = 0 TO oJSON.MemberCount
    IF CurPos = Index THEN
      ArrayNewMembers(CurPos) = NewMember
    ELSE
      IF CurPos > Index THEN
        ArrayNewMembers(CurPos) = ArrayOldMembers(CurPos - 1)
      ELSE
        ArrayNewMembers(CurPos) = ArrayOldMembers(CurPos)
      END IF
    END IF
  NEXT
  ERASE ArrayOldMembers
  oJSON.RawContent = JSON_GenerateObject(ArrayNewMembers())
  ERASE ArrayNewMembers
END SUB

SUB JSON_UpdateMember(oJSON AS JSON_Object, UpdatedMember AS JSON_Member)
  DIM ArrayMembers(oJSON.MemberCount - 1) AS JSON_Member
  JSON_ParseObject(oJSON, ArrayMembers())
  FOR CurPos AS ULONG = 0 TO oJSON.MemberCount - 1
    IF ArrayMembers(CurPos).Name = UpdatedMember.Name THEN
      ArrayMembers(CurPos) = UpdatedMember
      EXIT FOR
    END IF
  NEXT
  oJSON.RawContent = JSON_GenerateObject(ArrayMembers())
  ERASE ArrayMembers
END SUB

SUB JSON_DeleteMember (oJSON AS JSON_Object, MemberName AS STRING)
  DIM AS JSON_Member ArrayOldMembers(oJSON.MemberCount), ArrayNewMembers(oJSON.MemberCount - 2)
  DIM IsDeleted AS BYTE
  JSON_ParseObject(oJSON, ArrayOldMembers())
  FOR CurPos AS ULONG = 0 TO oJSON.MemberCount
    IF ArrayOldMembers(CurPos).Name = MemberName AND NOT IsDeleted THEN
      IsDeleted = -1
      CurPos += 1
    ELSE
      IF IsDeleted THEN
        ArrayNewMembers(CurPos - 2) = ArrayOldMembers(CurPos - 1)
      ELSE
        ArrayNewMembers(CurPos) = ArrayOldMembers(CurPos)
      END IF
    END IF
  NEXT
  ERASE ArrayOldMembers
  oJSON.RawContent = JSON_GenerateObject(ArrayNewMembers())
  ERASE ArrayNewMembers
END SUB
