local function identifierGeneratorFunction(suffix)
  local nextIndex = 0
  return function (specification)
    nextIndex = nextIndex + 1
    return specification.Identifier or
        (specification.Parent .. suffix .. nextIndex)
  end
end

local generateGridIdentifier = identifierGeneratorFunction("Grid")

local function addGrid(specification)
  local identifier = specification.Identifier or generateGridIdentifier(specification)

  local name = specification.Name
  local color = specification.Color
  local parent = specification.Parent
  local scale = specification.Scale
  local position = specification.Position
  local rotation = specification.Rotation

  local grid = {
    Identifier = identifier,
    Parent = parent,
    Transform = {
      Translation = {
        Type = "StaticTranslation",
        Position = position
      },
      Rotation = {
        Type = "StaticRotation",
        Rotation = rotation
      },
      Scale = {
        Type = "StaticScale",
        Scale = scale
      }
    },
    Renderable = {
      Type = "RenderableSphericalGrid",
      Enabled = true,
      LineWidth = 2.0,
      Color = color
  },
    GUI = {
      Name = name,
      Path = "/Other/Grids"
    }
  }
  openspace.addSceneGraphNode(grid)
  return identifier
end

local generateAxesIdentifier = identifierGeneratorFunction("Axes")

local function addCartesianAxes(specification)
  local identifier = specification.Identifier or generateAxesIdentifier(specification)

  local name = specification.Name or specification.Identifier
  local parent = specification.Parent or "Root"
  local scale = specification.Scale or { 1.0, 1.0, 1.0 }

  if type(scale) == "number" then
    scale = { scale, scale, scale }
  end

  local position = specification.Position or { 0.0, 0.0, 0.0 }
  local rotation = specification.Rotation or { 0.0, 0.0, 0.0 }

  local axes = {
    Identifier = identifier,
    Parent = parent,
    Transform = {
      Scale = {
        Type = "NonUniformStaticScale",
        Scale = scale
      },
      Translation = {
        Type = "StaticTranslation",
        Position = position
      },
      Rotation = {
        Type = "StaticRotation",
        Rotation = rotation
      }
    },
    Renderable = {
      Type = "RenderableCartesianAxes",
      Enabled = true,
      XColor = { 1.0, 0.0, 0.0 },
      YColor = { 0.0, 1.0, 0.0 },
      ZColor = { 0.0, 0.0, 1.0 }
    },
    GUI = {
      Name = name,
      Path = "/Other/Coordinate Systems"
    }
  }
  openspace.addSceneGraphNode(axes)
  return identifier
end


local function registerNode(containerAsset, nodeCreationFunction,
                            identifierGeneratorFunction, specification)
  local identifier = specification.Identifier or identifierGeneratorFunction(specification)

  specification.Identifier = identifier

  containerAsset.onInitialize(function()
    nodeCreationFunction(specification)
  end)
  containerAsset.onDeinitialize(function()
    openspace.removeSceneGraphNode(identifier)
  end)
end

local function registerGrid(gridAsset, specification)
  registerNode(gridAsset, addGrid, generateGridIdentifier, specification)
end

local function registerCartesianAxes(axesAsset, specification)
  registerNode(axesAsset, addCartesianAxes, generateAxesIdentifier, specification)
end

asset.export("addGrid", addGrid)
asset.export("registerGrid", registerGrid)

asset.export("addCartesianAxes", addCartesianAxes)
asset.export("registerCartesianAxes", registerCartesianAxes)
