scalar DateTime

type Language {
  iso: String!
}

type VideoCategory {
  id: ID!
  name: String
  videos: [Video!]
}

type License {
  id: ID!
  code: Int
  attribution: String
  customText: String
}

type PageInfo {
  hasNextPage: Boolean!
  hasPreviousPage: Boolean!

  startCursor: String
  endCursor: String
}

enum AssetAvailability {
  ACCEPTED
  PENDING
  INVALID
}

enum LiaisonJudgement {
  PENDING
  ACCEPTED
  REJECTED
}

enum WorkerType {
  GATEWAY
  STORAGE
}

type Worker {
  # unique ID
  id: ID!
  # ID of worker in the group, can be the same for different workers (in different groups)
  workerId: String!

  type: WorkerType!
  metadata: String
  isActive: Boolean!
}

type DataObject {
  id: ID!
  createdAt: DateTime!
  size: Float!
  # storage provider that accepted the asset
  liaison: Worker
  # status of asset as reported by liaison
  liaisonJudgement: LiaisonJudgement!
  # IPFS content id
  ipfsContentId: String!
  # Joystream runtime content id
  joystreamContentId: String!
}

type Membership {
  id: ID!
  handle: String!
  avatarUri: String
  controllerAccount: String!
  about: String
  channels: [Channel!]!
}

input MembershipWhereUniqueInput {
  id: ID
  handle: String
}

input MembershipWhereInput {
  controllerAccount_eq: ID
  controllerAccount_in: [ID!]
}

type Channel {
  id: ID!
  createdAt: DateTime!

  ownerMember: Membership
  videos: [Video!]!
  isCensored: Boolean!

  # === metadata ===
  title: String
  description: String
  isPublic: Boolean
  language: Language

  # === assets ===
  coverPhotoDataObject: DataObject
  coverPhotoUrls: [String!]!
  coverPhotoAvailability: AssetAvailability!
  avatarPhotoDataObject: DataObject
  avatarPhotoUrls: [String!]!
  avatarPhotoAvailability: AssetAvailability!

  # === extended from Orion ===
  follows: Int
}

input ChannelWhereInput {
  id_in: [ID!]
  ownerMemberId_eq: ID
  isCurated_eq: Boolean
  isPublic_eq: Boolean
  isCensored_eq: Boolean
  coverPhotoAvailability_eq: AssetAvailability
  avatarPhotoAvailability_eq: AssetAvailability
}

input ChannelWhereUniqueInput {
  id: ID!
}

enum ChannelOrderByInput {
  createdAt_ASC
  createdAt_DESC
}

type ChannelEdge {
  node: Channel!
  cursor: String!
}

type ChannelConnection {
  edges: [ChannelEdge!]!
  pageInfo: PageInfo!
  totalCount: Int!
}

type VideoMediaMetadata {
  id: ID!

  pixelWidth: Int
  pixelHeight: Int
  # Size in bytes
  size: Int
}

type Video {
  id: ID!
  createdAt: DateTime!
  channel: Channel!
  isCensored: Boolean!
  isFeatured: Boolean!
  publishedBeforeJoystream: DateTime

  # === metadata ===
  title: String
  description: String
  category: VideoCategory
  language: Language
  hasMarketing: Boolean
  isExplicit: Boolean
  isPublic: Boolean
  license: License

  # === assets ===
  thumbnailPhotoDataObject: DataObject
  thumbnailPhotoUrls: [String!]!
  thumbnailPhotoAvailability: AssetAvailability!
  mediaDataObject: DataObject
  mediaUrls: [String!]!
  mediaAvailability: AssetAvailability!

  mediaMetadata: VideoMediaMetadata!
  # In seconds
  duration: Int
  skippableIntroDuration: Int

  # === extended from Orion ===
  views: Int
}

input VideoCategoryWhereUniqueInput {
  id: ID!
}

input VideoWhereInput {
  categoryId_eq: ID
  channelId_in: [ID!]
  channelId_eq: ID
  thumbnailPhotoAvailability_eq: AssetAvailability
  mediaAvailability_eq: AssetAvailability
  createdAt_gte: DateTime
  isFeatured_eq: Boolean
  isPublic_eq: Boolean
  isCensored_eq: Boolean
  id_in: [ID!]
}

input VideoWhereUniqueInput {
  id: ID!
}

enum VideoOrderByInput {
  createdAt_ASC
  createdAt_DESC
}

type VideoEdge {
  node: Video!
  cursor: String!
}

type VideoConnection {
  edges: [VideoEdge!]!
  pageInfo: PageInfo!
  totalCount: Int!
}

input WorkerWhereInput {
  metadata_contains: String
  isActive_eq: Boolean
  type_eq: WorkerType
}

input WorkerWhereUniqueInput {
  id: ID!
}

enum WorkerOrderByInput {
  createdAt_ASC
  createdAt_DESC
}
# Isn't provided by query node yet
type CoverVideo {
  id: ID!
  video: Video!
  coverDescription: String!
  coverCutMediaMetadata: VideoMediaMetadata!
  coverCutMediaDataObject: DataObject
  coverCutMediaAvailability: AssetAvailability!
  coverCutMediaUrl: String
}

union SearchResult = Video | Channel

type SearchFTSOutput {
  item: SearchResult!
  rank: Float!
  isTypeOf: String!
  highlight: String!
}

type ProcessorState {
  lastCompleteBlock: Float!
  lastProcessedEvent: String!
  indexerHead: Float!
  chainHead: Float!
}

type Query {
  # Lookup a membership by its ID
  membershipByUniqueInput(where: MembershipWhereUniqueInput!): Membership

  # Lookup all memberships by account ID
  memberships(where: MembershipWhereInput!): [Membership!]!

  # Lookup a channel by its ID
  channelByUniqueInput(where: ChannelWhereUniqueInput!): Channel

  # List all channels by given constraints
  channels(where: ChannelWhereInput): [Channel!]!

  # List all channel by given constraints
  channelsConnection(
    first: Int
    after: String
    where: ChannelWhereInput
    orderBy: ChannelOrderByInput
  ): ChannelConnection!

  # Lookup video by its ID
  videoByUniqueInput(where: VideoWhereUniqueInput!): Video

  # Lookup videos by where params
  videos(offset: Int, limit: Int, where: VideoWhereInput, orderBy: VideoOrderByInput): [Video!]

  # List all videos by given constraints
  videosConnection(first: Int, after: String, where: VideoWhereInput, orderBy: VideoOrderByInput): VideoConnection!

  # List all categories
  videoCategories: [VideoCategory!]!

  workers(offset: Int, limit: Int, where: WorkerWhereInput): [Worker!]

  workerByUniqueInput(where: WorkerWhereUniqueInput!): Worker

  # Get the current cover video
  coverVideo: CoverVideo!

  # Free text search across videos and channels
  search(limit: Int, text: String!): [SearchFTSOutput!]!
}

type Subscription {
  stateSubscription: ProcessorState!
}
