import jsonParse from "./jsonParse"

export default () => {
  let jsonAST = {}
  let path = []

  const init = (jsonStr) => {
    jsonAST = jsonParse(jsonStr)
    linkParents(jsonAST)
  }

  const setNewText = (jsonStr) => {
    init(jsonStr)
    path = []
  }

  const linkParents = (node) => {
    if (node.kind == "Object") {
      if (node.members) {
        node.members.forEach((m) => {
          m.parent = node
          linkParents(m)
        })
      }
    } else if (node.kind == "Array") {
      if (node.values) {
        node.values.forEach((v) => {
          v.parent = node
          linkParents(v)
        })
      }
    } else if (node.kind == "Member") {
      if (node.value) {
        node.value.parent = node
        linkParents(node.value)
      }
    }
  }

  const genPath = (index) => {
    let output = {}
    path = []
    let current = jsonAST
    if (current.kind == "Object") {
      path.push({ label: "{}", obj: "root" })
    } else if (current.kind == "Array") {
      path.push({ label: "[]", obj: "root" })
    }
    let over = false

    try {
      while (!over) {
        if (current.kind == "Object") {
          let i = 0
          let found = false
          while (i < current.members.length) {
            let m = current.members[i]
            if (m.start <= index && m.end >= index) {
              path.push({ label: m.key.value, obj: m })
              current = current.members[i]
              found = true
              break
            }
            i++
          }
          if (!found) over = true
        } else if (current.kind == "Array") {
          if (current.values) {
            let i = 0
            let found = false
            while (i < current.values.length) {
              let m = current.values[i]
              if (m.start <= index && m.end >= index) {
                path.push({ label: `[${i.toString()}]`, obj: m })
                current = current.values[i]
                found = true
                break
              }
              i++
            }
            if (!found) over = true
          } else over = true
        } else if (current.kind == "Member") {
          if (current.value) {
            if (current.value.start <= index && current.value.end >= index) {
              current = current.value
            } else over = true
          } else over = true
        } else if (
          current.kind == "String" ||
          current.kind == "Number" ||
          current.kind == "Boolean" ||
          current.kind == "Null"
        ) {
          if (current.start <= index && current.end >= index) {
            path.push({ label: `${current.value}`, obj: current })
          }
          over = true
        }
      }
      output = { success: true, res: path.map((p) => p.label) }
    } catch (e) {
      output = { success: false, res: e }
    }
    return output
  }

  const getSiblings = (index) => {
    let parent = path[index].obj.parent
    if (!parent) return []
    else {
      if (parent.kind == "Object") {
        return parent.members
      } else if (parent.kind == "Array") {
        return parent.values
      } else return []
    }
  }

  return {
    init,
    genPath,
    getSiblings,
    setNewText,
  }
}
