enum _UserOrdering {
  id_asc
  id_desc
  name_asc
  name_desc
  slug_asc
  slug_desc
  role_asc
  role_desc
  locationName_asc
  locationName_desc
  about_asc
  about_desc
  createdAt_asc
  createdAt_desc
  updatedAt_asc
  updatedAt_desc
  locale_asc
  locale_desc
}

type User {
  id: ID!
  actorId: String
  name: String
  email: String! @cypher(statement: "MATCH (this)-[:PRIMARY_EMAIL]->(e:EmailAddress) RETURN e.email")
  slug: String!
  avatar: Image @relation(name: "AVATAR_IMAGE", direction: "OUT")
  deleted: Boolean
  disabled: Boolean
  role: UserRole!
  publicKey: String
  invitedBy: User @relation(name: "INVITED", direction: "IN")
  invited: [User] @relation(name: "INVITED", direction: "OUT")

  locationName: String
  location: Location @cypher(statement: "MATCH (this)-[:IS_IN]->(l:Location) RETURN l")
  about: String
  socialMedia: [SocialMedia]! @relation(name: "OWNED_BY", direction: "IN")

  createdAt: String
  updatedAt: String

  termsAndConditionsAgreedVersion: String
  termsAndConditionsAgreedAt: String

  allowEmbedIframes: Boolean
  showShoutsPublicly: Boolean
  sendNotificationEmails: Boolean
  locale: String
  friends: [User]! @relation(name: "FRIENDS", direction: "BOTH")
  friendsCount: Int! @cypher(statement: "MATCH (this)<-[:FRIENDS]->(r:User) RETURN COUNT(DISTINCT r)")

  following: [User]! @relation(name: "FOLLOWS", direction: "OUT")
  followingCount: Int! @cypher(statement: "MATCH (this)-[:FOLLOWS]->(r:User) RETURN COUNT(DISTINCT r)")

  followedBy: [User]! @relation(name: "FOLLOWS", direction: "IN")
  followedByCount: Int! @cypher(statement: "MATCH (this)<-[:FOLLOWS]-(r:User) RETURN COUNT(DISTINCT r)")

  inviteCodes: [InviteCode] @relation(name: "GENERATED", direction: "OUT")
  redeemedInviteCode: InviteCode @relation(name: "REDEEMED", direction: "OUT")

  # Is the currently logged in user following that user?
  followedByCurrentUser: Boolean! @cypher(
  statement: """
  MATCH (this)<-[:FOLLOWS]-(u:User { id: $cypherParams.currentUserId})
  RETURN COUNT(u) >= 1
  """
  )

  isBlocked: Boolean! @cypher(
  statement: """
  MATCH (this)<-[:BLOCKED]-(user:User {id: $cypherParams.currentUserId})
  RETURN COUNT(user) >= 1
  """
  )
  blocked: Boolean! @cypher(
  statement: """
  MATCH (this)-[:BLOCKED]-(user:User {id: $cypherParams.currentUserId})
  RETURN COUNT(user) >= 1
  """
  )

  isMuted: Boolean! @cypher(
  statement: """
  MATCH (this)<-[:MUTED]-(user:User { id: $cypherParams.currentUserId})
  RETURN COUNT(user) >= 1
  """
  )
  
  # contributions: [WrittenPost]!
  # contributions2(first: Int = 10, offset: Int = 0): [WrittenPost2]!
  # @cypher(
  # statement: "MATCH (this)-[w:WROTE]->(p:Post) RETURN p as Post, w.timestamp as timestamp"
  # )
  contributions: [Post]! @relation(name: "WROTE", direction: "OUT")
  contributionsCount: Int! @cypher(
  statement: """
  MATCH (this)-[:WROTE]->(r:Post)
  WHERE NOT r.deleted = true AND NOT r.disabled = true
  RETURN COUNT(r)
  """
  )

  comments: [Comment]! @relation(name: "WROTE", direction: "OUT")
  commentedCount: Int! @cypher(statement: "MATCH (this)-[:WROTE]->(:Comment)-[:COMMENTS]->(p:Post) WHERE NOT p.deleted = true AND NOT p.disabled = true RETURN COUNT(DISTINCT(p))")

  shouted: [Post]! @relation(name: "SHOUTED", direction: "OUT")
  shoutedCount: Int! @cypher(statement: "MATCH (this)-[:SHOUTED]->(r:Post) WHERE NOT r.deleted = true AND NOT r.disabled = true RETURN COUNT(DISTINCT r)")

  categories: [Category] @relation(name: "CATEGORIZED", direction: "OUT")

  badges: [Badge]! @relation(name: "REWARDED", direction: "IN")
  badgesCount: Int! @cypher(statement: "MATCH (this)<-[:REWARDED]-(r:Badge) RETURN COUNT(r)")

  emotions: [EMOTED]

  activeCategories: [String] @cypher(
  statement: """
  MATCH (category:Category)
  WHERE NOT ((this)-[:NOT_INTERESTED_IN]->(category))
  RETURN collect(category.id)
  """
  )

  myRoleInGroup: GroupMemberRole
}


input _UserFilter {
  AND: [_UserFilter!]
  OR: [_UserFilter!]
  name_contains: String
  about_contains: String
  slug_contains: String
  id: ID
  id_not: ID
  id_in: [ID!]
  id_not_in: [ID!]
  friends: _UserFilter
  friends_not: _UserFilter
  friends_in: [_UserFilter!]
  friends_not_in: [_UserFilter!]
  friends_some: _UserFilter
  friends_none: _UserFilter
  friends_single: _UserFilter
  friends_every: _UserFilter
  following: _UserFilter
  following_not: _UserFilter
  following_in: [_UserFilter!]
  following_not_in: [_UserFilter!]
  following_some: _UserFilter
  following_none: _UserFilter
  following_single: _UserFilter
  following_every: _UserFilter
  followedBy: _UserFilter
  followedBy_not: _UserFilter
  followedBy_in: [_UserFilter!]
  followedBy_not_in: [_UserFilter!]
  followedBy_some: _UserFilter
  followedBy_none: _UserFilter
  followedBy_single: _UserFilter
  followedBy_every: _UserFilter
  role_in: [UserRole!]
}

type Query {
  User(
    id: ID
    email: String # admins need to search for a user sometimes
    name: String
    slug: String
    role: UserRole
    locationName: String
    about: String
    createdAt: String
    updatedAt: String
    first: Int
    offset: Int
    orderBy: [_UserOrdering]
    filter: _UserFilter
  ): [User]

  availableRoles: [UserRole]! 
  mutedUsers: [User]
  blockedUsers: [User]
  isLoggedIn: Boolean!
  currentUser: User
}

enum Deletable {
  Post
  Comment
}

type Mutation {
  UpdateUser (
    id: ID!
    name: String
    email: String
    slug: String
    avatar: ImageInput
    locationName: String # empty string '' sets it to null
    about: String
    termsAndConditionsAgreedVersion: String
    termsAndConditionsAgreedAt: String
    allowEmbedIframes: Boolean
    showShoutsPublicly: Boolean
    sendNotificationEmails: Boolean
    locale: String
  ): User

  DeleteUser(id: ID!, resource: [Deletable]): User

  muteUser(id: ID!): User
  unmuteUser(id: ID!): User

  blockUser(id: ID!): User
  unblockUser(id: ID!): User

  followUser(id: ID!): User
  unfollowUser(id: ID!): User

  switchUserRole(role: UserRole!, id: ID!): User

  saveCategorySettings(activeCategories: [String]): Boolean

  requestPasswordReset(email: String!): Boolean!
  resetPassword(email: String!, nonce: String!, newPassword: String!): Boolean!
  changePassword(oldPassword: String!, newPassword: String!): String!

  # Get a JWT Token for the given Email and password
  login(email: String!, password: String!): String!
}
