enum Network {
  BABYLON
  ALEXANDRIA
  ROME
}

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"
  createdInBlock: Int!

  "How the member was registered"
  entry: MembershipEntryMethod!

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

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

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

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

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

  createdInBlock: Int!
}

"Asset availability representation"
enum AssetAvailability {
  "Asset is available in storage"
  ACCEPTED,

  "Asset is being uploaded to storage"
  PENDING,

  "Invalid storage (meta)data used"
  INVALID,
}

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

  "Content accepted"
  ACCEPTED,
}

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

  "Content added at"
  createdInBlock: Int!

  "Content type id"
  typeId: Int!

  "Content size in bytes"
  size: Int!

  "Storage provider id of the liaison"
  liaison: Worker # liaison is unset until storage provider accepts or rejects the content

  "Storage provider as liaison judgment"
  liaisonJudgement: LiaisonJudgement!

  "IPFS content id"
  ipfsContentId: String!

  "Joystream runtime content"
  joystreamContentId: String!
}

"Owner type for storage object"
union DataObjectOwner = DataObjectOwnerMember
  | DataObjectOwnerChannel
  | DataObjectOwnerDao
  | DataObjectOwnerCouncil
  | DataObjectOwnerWorkingGroup

"Asset owned by a member"
type DataObjectOwnerMember @variant {
  # use `Int` instead of `Membership` before variant relations are featured in Hydra
  # TODO: setup proper relations
  #"Member identifier"
  #memberId: Membership!
  "Member identifier"
  member: Int!

  "Variant needs to have at least one property. This value is not used."
  dummy: Int
}

"Asset owned by a channel"
type DataObjectOwnerChannel @variant {
  # use `Int` instead of `Channel` before variant relations are featured in Hydra
  #"Channel identifier"
  #channel: Channel!
  "Channel identifier"
  channel: Int!

  "Variant needs to have at least one property. This value is not used."
  dummy: Int
}

"Asset owned by a DAO"
type DataObjectOwnerDao @variant {
  "DAO identifier"
  dao: Int!
}

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

"Asset owned by a WorkingGroup"
type DataObjectOwnerWorkingGroup @variant {
  "Working group identifier"
  workingGroup: Int!
}

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

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

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

  createdInBlock: Int!
}

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

  "Member owning the channel (if any)"
  ownerMember: Membership

  "Curator group owning the channel (if any)"
  ownerCuratorGroup: CuratorGroup

  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

  ### Cover photo asset ###

  # Channel's cover (background) photo. Recommended ratio: 16:9.

  "Asset's data object"
  coverPhotoDataObject: DataObject

  "URLs where the asset content can be accessed (if any)"
  coverPhotoUrls: [String!]

  "Availability meta information"
  coverPhotoAvailability: AssetAvailability!

  ### Avatar photo asset ###

  # Channel's avatar photo.

  "Asset's data object"
  avatarPhotoDataObject: DataObject

  "URLs where the asset content can be accessed (if any)"
  avatarPhotoUrls: [String!]

  "Availability meta information"
  avatarPhotoAvailability: AssetAvailability!

  ##########################

  "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")

  createdInBlock: Int!
}

type CuratorGroup @entity {
  "Runtime identifier"
  id: ID!

  "Curators belonging to this group"
  curatorIds: [Int!]!

  "Is group active or not"
  isActive: Boolean!

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

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

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

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

  createdInBlock: Int!
}

type Video @entity {
  "Runtime identifier"
  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

  ### Thumbnail asset ###

  # Video thumbnail (recommended ratio: 16:9)

  "Asset's data object"
  thumbnailPhotoDataObject: DataObject

  "URLs where the asset content can be accessed (if any)"
  thumbnailPhotoUrls: [String!]

  "Availability meta information"
  thumbnailPhotoAvailability: AssetAvailability!

  ##########################

  "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

  ### Media asset ###

  # Reference to video asset

  "Asset's data object"
  mediaDataObject: DataObject

  "URLs where the asset content can be accessed (if any)"
  mediaUrls: [String!]

  "Availability meta information"
  mediaAvailability: AssetAvailability!

  ##########################

  "Video file metadata"
  mediaMetadata: VideoMediaMetadata

  createdInBlock: Int!

  "Is video featured or not"
  isFeatured: Boolean!
}

type VideoMediaMetadata @entity {
  "Unique identifier"
  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")

  createdInBlock: Int!
}

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

  "Media container format"
  container: String

  "Content MIME type"
  mimeMediaType: String
}

type License @entity {
  "Unique identifier"
  id: ID!

  "License code defined by Joystream"
  code: Int

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

  "Custom license content"
  custom_text: String
}

enum WorkerType {
  GATEWAY
  STORAGE
}

type Worker @entity {
  "Unique identifier"
  id: ID!

  "Sign of worker still being active"
  isActive: Boolean!

  "Runtime identifier"
  workerId: String!

  "Associated working group"
  type: WorkerType!

  "Custom metadata set by provider"
  metadata: String

  dataObjects: [DataObject!]! @derivedFrom(field: "liaison")
}

type NextEntityId @entity {
  "Unique identifier"
  id: ID!

  "Next deterministic id for entities without custom id"
  nextId: Int!
}