enum Network {
  BABYLON
  ALEXANDRIA
  ROME
}

type Block @entity {
  "Block number as a string"
  id: ID!
  block: Int!
  executedAt: DateTime!
  network: Network!
}

enum MembershipEntryMethod {
  PAID
  SCREENING
  GENESIS
}

"Stored information about a registered user"
type Membership @entity {
  "MemberId: runtime identifier for a user"
  id: ID!

  "The unique handle chosen by member"
  handle: String! @unique @fulltext(query: "membersByHandle")

  "A Url to member's Avatar image"
  avatarUri: String

  "Short text chosen by member to share information about themselves"
  about: String

  "Member's controller account id"
  controllerAccount: String!

  "Member's root account id"
  rootAccount: String!

  "Blocknumber when member was registered"
  registeredAtBlock: Block!

  "Timestamp when member was registered"
  registeredAtTime: DateTime!

  "How the member was registered"
  entry: MembershipEntryMethod!

  "The type of subscription the member has purchased if any."
  subscription: BigInt
}

"Category of media channel"
type ChannelCategory @entity {
  id: ID!

  "The name of the category"
  name: String @fulltext(query: "channelCategoriesByName")

  channels: [Channel!] @derivedFrom(field: "category")

  happenedIn: Block!
}

"Storage asset"
union Asset = AssetUrl | AssetStorage

"Asset stored at an external source"
type AssetUrl @variant {
  id: ID!

  "The http url pointing to the media"
  url: String!
}

"Asset was never fully uploaded."
type AssetNeverProvided @variant {
  happenedIn: Block!
}

"Asset was deleted and is no longer available."
type AssetDeleted @variant {
  happenedIn: Block!
}

"Status of an asset upload"
type AssetUploadStatus @variant {
  """
  Data object in upload life-cycle.
  If this is deleted, then set oldDataObject in its place if it is set and not rejected, otherwise union goes to Deleted.
  """
  dataObject: AssetDataObject!

  """
  Possible prior data object which was in some stage of upload life-cycle when new one was initiated.
  If accepted, then apps may chose to use old in place of new before it is accepted.
  If this is deleted, then set to null.
  """
  oldDataObject: AssetDataObject

  happenedIn: Block!
}

union AssetStorageUploadStatus = AssetNeverProvided | AssetDeleted | AssetUploadStatus

type AssetStorage @variant {
  id: ID!

  "Upload to content directory status"
  uploadStatus: AssetStorageUploadStatus!
}

"The decision of the storage provider when it acts as liaison"
enum LiaisonJudgement {
  "Content awaits for a judgment"
  PENDING,

  "Content accepted"
  ACCEPTED,

  "Content rejected"
  REJECTED,
}

"Manages content ids, type and storage provider decision about it"
type AssetDataObject @entity {
  "Content owner"
  owner: AssetOwner!

  "Content added at"
  addedAt: Block!

  "Content type id"
  typeId: Int!

  "Content size in bytes"
  size: BigInt!

  "Storage provider id of the liaison"
  liaisonId: BigInt!

  "Storage provider as liaison judgment"
  liaisonJudgement: LiaisonJudgement!

  "IPFS content id"
  ipfsContentId: String!

  "Joystream runtime content"
  joystreamContentId: String!
}

"Owner type for storage object"
union AssetOwner = AssetOwnerMember | AssetOwnerChannel | AssetOwnerDao | AssetOwnerCouncil | AssetOwnerWorkingGroup

"Asset owned by a member"
type AssetOwnerMember @variant {
  "Member identifier"
  memberId: BigInt!
}

"Asset owned by a channel"
type AssetOwnerChannel @variant {
  "Channel identifier"
  channel: Channel!
}

"Asset owned by a DAO"
type AssetOwnerDao @variant {
  "DAO identifier"
  daoId: BigInt!
}

"Asset owned by the Council"
type AssetOwnerCouncil @variant {
  "Variant needs to have at least one property. This value is not used."
  dummy: Int!
}

"Asset owned by a WorkingGroup"
type AssetOwnerWorkingGroup @variant {
  "Working group identifier"
  workingGroupId: BigInt!
}

#### High Level Derivative Entities ####

type Language @entity {
  "Runtime entity identifier (EntityId)"
  id: ID!

  "Language identifier ISO 639-1"
  iso: String!

  happenedIn: Block!
}

type Channel @entity {
  "Runtime entity identifier (EntityId)"
  id: ID!

  #"Owner of the channel"
  owner: ChannelOwner!

  category: ChannelCategory

  "Reward account where revenue is sent if set."
  rewardAccount: String

  "The title of the Channel"
  title: String @fulltext(query: "search")

  "The description of a Channel"
  description: String

  "Channel's cover (background) photo. Recommended ratio: 16:9."
  coverPhoto: Asset

  "Channel's avatar photo."
  avatarPhoto: Asset

  "Flag signaling whether a channel is public."
  isPublic: Boolean

  "Flag signaling whether a channel is censored."
  isCensored: Boolean!

  "The primary langauge of the channel's content"
  language: Language

  videos: [Video!] @derivedFrom(field: "channel")

  happenedIn: Block!
}

"Channel owner"
union ChannelOwner = ChannelOwnerMember | ChannelCuratorGroup | ChannelOwnerDao

type ChannelOwnerMember @variant {
  "Member identifier"
  memberId: BigInt!
}

type ChannelCuratorGroup @variant {
  "Curator group identifier"
  curatorGroupId: BigInt!
}

type ChannelOwnerDao @variant {
  "DAO identifier"
  daoId: BigInt!
}

type CuratorGroup @entity {
  "Curators belonging to this group"
  curratorIds: [BigInt!]

  "Is group active or not"
  is_active: Boolean
}

type VideoCategory @entity {
  "Runtime entity identifier (EntityId)"
  id: ID!

  "The name of the category"
  name: String @fulltext(query: "videoCategoriesByName")

  videos: [Video!] @derivedFrom(field: "category")

  happenedIn: Block!
}

type Video @entity {
  "Runtime entity identifier (EntityId)"
  id: ID!

  "Reference to member's channel"
  channel: Channel!

  "Reference to a video category"
  category: VideoCategory

  "The title of the video"
  title: String @fulltext(query: "search")

  "The description of the Video"
  description: String

  "Video duration in seconds"
  duration: Int

  "Video thumbnail (recommended ratio: 16:9)"
  thumbnailPhoto: Asset

  "Video's main langauge"
  language: Language

  "Whether or not Video contains marketing"
  hasMarketing: Boolean

  "If the Video was published on other platform before beeing published on Joystream - the original publication date"
  publishedBeforeJoystream: DateTime

  "Whether the Video is supposed to be publically displayed"
  isPublic: Boolean

  "Flag signaling whether a video is censored."
  isCensored: Boolean!

  "Whether the Video contains explicit material."
  isExplicit: Boolean

  "License under the video is published"
  license: License

  "Reference to video asset"
  media: Asset

  "Video file metadata"
  mediaMetadata: VideoMediaMetadata

  happenedIn: Block!

  "Is video featured or not"
  isFeatured: Boolean!

  featured: FeaturedVideo @derivedFrom(field: "video")
}

type VideoMediaMetadata @entity {
  "Runtime entity identifier (EntityId)"
  id: ID!

  "Encoding of the video media object"
  encoding: VideoMediaEncoding

  "Video media width in pixels"
  pixelWidth: Int

  "Video media height in pixels"
  pixelHeight: Int

  "Video media size in bytes"
  size: Int

  video: Video @derivedFrom(field: "mediaMetadata")

  happenedIn: Block!
}

type VideoMediaEncoding @entity {
  "Encoding of the video media object"
  codecName: String

  "Media container format"
  container: String

  "Content MIME type"
  mimeMediaType: String
}

type License @entity {
  "Runtime entity identifier (EntityId)"
  id: ID!

  "License code defined by Joystream"
  code: Int

  "Attribution (if required by the license)"
  attribution: String

  "Custom license content"
  custom_text: String
}

type FeaturedVideo @entity {
  "Runtime entity identifier (EntityId)"
  id: ID!

  "Reference to a video"
  video: Video!
}
