schema {
  query: query
  mutation: mutation
}

"Annotations object"
type Annotation {
  "GraphID for annotation node"
  graphId: String
  context: String!

  "id"
  id: String!

  "object type"
  type: EntityType!

  "Annotation motivation"
  motivation: String!

  "The agent responsible for creation of annotation"
  creator: Creator!

  "The date-time of creation of annotation"
  created: String!

  "The agent responsible for generation of annotation"
  generator: Generator!

  "Date-time of generation of annotation"
  generated: String!

  "Annotation body"
  body: [bodyType!]

  "Annotation target"
  target: [targetType!]!
}

input AnnotationInput {
  targetId: String!
  motivation: String!
  body: BodyInput!
  target: Target!
  concept: String
}

type AuthPayload {
  token: String!
  user: User!
}

input BodyInput {
  typ: String!
  motivation: String!
  value: String!
  format: String!
  language: String!
  creator: String!
  concept: String
}

input Comment {
  targetId: String!
  value: String!
}

type Creator {
  graphId: String!
  typ: EntityType!
  name: String!
  nickname: String!
}

input CsvIngestInput {
  filePath: String!
  crosswalk: [FlatRecordMapper!]!
  partner: PartnerInput!
}

"Date range, inclusive"
type DateRange {
  "Date starting from"
  from: String!

  "Date ending"
  to: String!
}

"ISO-8601 formatted string of format: 2017-06-25"
input DateRangeInput {
  from: String!
  to: String!
}

type EntityFilter {
  blob: String!
  lang: [Language!]
  dateRange: DateRange
  subjects: [Subject!]
  people: [Person!]
  places: [Place!]
  partners: [Partner!]
}

input EntityFilterInput {
  blob: String!
  dateRange: DateRangeInput
  lang: [String!]
  subjects: [String!]
  people: [String!]
  places: [String!]
  partners: [String!]
}

enum EntityType {
  Text
  Sound
  Video
  Image
  Dataset
  SpecificResource
  TextualBody
  LocalResource
  Software
  Client
  Ni
  User
  Partner
  Person
  Annotation
  MilliEntity
  Language
  Place
  Subject
}

"""
Map from a flat-record to any level of 
      nested record structure. Ensure column names are unique.
"""
input FlatRecordMapper {
  field: ValidField!
  columnName: String!
  default: String!
}

type Generator {
  graphId: String!
  typ: EntityType!
  name: String!
  homepage: String!
}

type Image {
  graphId: String!
  typ: EntityType!
  src: String!
  alt: String
  size: ImageSize!
}

enum ImageSize {
  LARGE
  MEDIUM
  SMALL
}

type Language {
  graphId: String!
  typ: EntityType!
  langId: String!
  displayName: String!
  isSelected: Boolean!
}

"LocalResource wraps a NiosxEntity as the body of the annotation."
type LocalResource {
  "One of NiosxEntity types"
  entity: NiosxEntityUnion

  "IRI of the LocalResource"
  iri: String!

  "GraphId of the LocalResource"
  graphId: String!

  "IRI of the Body"
  source: String!

  "Concept with which the Body is attached to the Entity."
  concept: NiosxConcept!

  "Type of the Body entity."
  type: EntityType!
}

type MilliEntity {
  graphId: String!
  typ: EntityType!
  agencyCode: String!
  recordId: String!
  unitId: String!
  title: String!
  creator: String!
  dateOfCreation: String!
  extent: String!
  level: String!
  partner: Partner!
  subjects: [Subject!]!
  images: [Image!]!
  description: String
  location: String
  accessRestrict: String
  useRestrict: String
  language: String
  unitType: String
  format: String
  annotations: [Annotation!]!
}

"The concept layer connecting all entities via annotations."
type NiosxConcept {
  """
  Name of the concept. 
            This is one of system defined values or a user given name.
  """
  name: String!
}

"All Types identified by the niosx ecosystem"
interface NiosxEntity {
  "A unique identity for the entity in the niosx ecosystem."
  graphId: String!

  "The `type` is a String representation of the entity type."
  type: EntityType!
}

input NiosxEntityInput {
  agencyCode: String!
  recordId: String!
  unitId: String!
  title: String!
  creator: String!
  dateOfCreation: String!
  extent: String!
  level: String!
  partner: String!
  description: String
  location: String
  accessRestrict: String
  useRestrict: String
  language: String
  unitType: String
  format: String
}

"Is one the the niosx Entities."
union NiosxEntityUnion = TextualBody | LocalResource | Subject

input NiosxUser {
  username: String!
  password: String!
  role: String!
}

type Page {
  edges: [PageEdge!]!
  pageInfo: PageInfo!
}

type PageEdge {
  node: MilliEntity!
  cursor: String!
  offset: Long!
  isDirectMatch: Boolean!
  annotationMatchCount: Int!
}

type PageInfo {
  pageNumber: Int!
  endCursor: String!
  hasNextPage: Boolean!
  filters: EntityFilter!
}

type Partner {
  graphId: String!
  typ: EntityType!
  displayName: String!
  isSelected: Boolean!
}

input PartnerInput {
  graphId: String = "4ebb7326-dcbb-4056-bff3-7c76c059a000"
  typ: EntityType = Partner
  displayName: String!
  isSelected: Boolean = true
}

type Person {
  graphId: String!
  typ: EntityType!
  displayName: String!
  isSelected: Boolean!
}

type Place {
  graphId: String!
  typ: EntityType!
  lat: Float!
  lon: Float!
  displayName: String!
  isSelected: Boolean!
}

type SpecificResourceType {
  graphId: String!
  typ: EntityType!
  source: String!
  targetId: String!
}

type Subject {
  graphId: String!
  typ: EntityType!
  prefLabel: String!
  inScheme: String!
  id: String!
  isSelected: Boolean!
}

input SubjectAnnoInput {
  targetId: String!
  subjectId: String
  prefLabel: String
}

input SubjectIn {
  prefLabel: String!
  inScheme: String!
  id: String!
}

input Target {
  source: String!
  targetId: String!
}

type TextualBody implements NiosxEntity {
  graphId: String!
  typ: EntityType!
  iri: String!
  purpose: String!
  value: String!
  format: String!
  language: String!
  creator: String!
  concept: NiosxConcept!

  "The `type` is a String representation of the entity type."
  type: EntityType!
}

type User {
  username: String!
  permissions: [String!]
}

enum ValidField {
  ME_format
  ME_unitType
  ME_language
  ME_useRestrict
  ME_accessRestrict
  ME_location
  ME_description
  ME_subject
  ME_image
  ME_level
  ME_extent
  ME_dateOfCreation
  ME_creator
  ME_title
  ME_unitId
  ME_agencyCode
  ME_recordId
}

"Can be one of TextualBodyType, etc."
union bodyType = TextualBody | LocalResource

type mutation {
  rdfIngest(rdf_file: String!, schema: String!): Int!
  ingestWithCrosswalk(csvIngestInput: CsvIngestInput!): Int!
  addEntity(niosxEntityInput: NiosxEntityInput!): MilliEntity
  addAnnotation(annotation: AnnotationInput!): Annotation
  addSubAnno(subjectAnno: SubjectAnnoInput!): Annotation
  addComment(comment: Comment!): Annotation
  addSubject(SubjectIn: SubjectIn!): Subject
  login(username: String!, password: String!): AuthPayload
  register(niosxUserInput: NiosxUser!): String!
}

type query {
  "Paginated list of entities"
  searchCollections(next: Int!, cursor: String, entityFilterInputArg: EntityFilterInput!): Page

  "Returns everything! Be careful!"
  crudeSearch(blob: String!): [MilliEntity!]!

  "Test if there is an object with this graphId"
  isValidGraphId(id: String!): Boolean!

  "Look up an entity with its graphId"
  findEntity(id: String!): MilliEntity

  "Look up a user with its username"
  findUser(username: String!): User
}

"Can be one of SpecificResource, etc."
union targetType = SpecificResourceType