type SubscriptionData {
    endpoint: String!
    topic: String!
}

# USER

enum UserAccessStatus {
    SMS_MFA
    SOFTWARE_TOKEN_MFA
    SELECT_MFA_TYPE
    MFA_SETUP
    PASSWORD_VERIFIER
    CUSTOM_CHALLENGE
    DEVICE_SRP_AUTH
    DEVICE_PASSWORD_VERIFIER
    ADMIN_NO_SRP_AUTH
    NEW_PASSWORD_REQUIRED
    LOGGED_IN
}

enum UserDeliveryMedium {
    SMS
    EMAIL
}

type UserAccessResponse {
    status: UserAccessStatus!
    session: String
    idToken: String
    accessToken: String
    refreshToken: String
}

type UserSignUpResponse {
    deliveryMedium: UserDeliveryMedium
    userConfirmed: Boolean!
}

input UserSignUpMutationInput {
    username: String!
    password: String!
}

input UserAccessTokenQueryInput {
    username: String!
    password: String!
}

input UserSetNewPasswordInput {
    username: String!
    password: String!
    session: String!
}

input UserConfirmSignUpInput {
    username: String!
    confirmationCode: String!
}

input UserRefreshAccessTokenInput {
    refreshToken: String!
}

# SCRIPT

enum ScriptPlatformOS {
    linux
}

type ScriptPlatform {
    os: ScriptPlatformOS!
    dist: String!
    codename: String!
}

type ScriptMetadata {
    version: String!
    platform: [ScriptPlatform]
}

type ScriptDependency {
    name: String!
    version: String!
}

type ScriptFixedDependency {
    name: String!
    namespace: String
    version: String!
}

input ScriptDependencyInput {
    name: String!
    version: String!
}

input ScriptPlatformInput {
    os: ScriptPlatformOS!
    dist: String!
    codename: String!
}

type Script {
    version: String!
    description: String!
    category: Category!
    readme: AssetContent!
    execute: AssetContent!
    superuser: Boolean!
    dependencies: [ScriptDependency]
    resolvedDependencies: [ScriptFixedDependency]
    platform: [ScriptPlatform]
}

input ScriptQueryInput {
    name: String!
    namespace: String
    version: String!
}

input ScriptVersionsQueryInput {
    name: String!
    namespace: String
}

# ASSETS

type Asset {
    id: ID!
}

type AssetContent {
    id: String!
    content: String!
}

input AssetContentMutationInput {
    content: String!
}

input AssetContentQueryInput {
    id: ID!
}

# PACKAGE

type PackageActivitiesStats {
    latestRelease: String!
    successful: Int!
    failed: Int!
}

type PackageActivitiesTimelineEntry {
    datetime: String!
    successful: Int!
    failed: Int!
}

type Package {
    id: ID!
    name: String!
    namespace: String
    readme: AssetContent!
    description: String!
    category: Category!
    scriptMetadata: [ScriptMetadata]!
    activities: [Activity]!
    stats: PackageActivitiesStats!
    activitiesTimeline: [PackageActivitiesTimelineEntry]!
}

type PackageMetadata {
    name: String!
    namespace: String
    description: String!
}

input PackageQueryInput {
    name: String!
    namespace: String
}

input UserPackagesQueryInput {
    username: String!
}

input PublishMutationInput {
    name: String!
    namespace: String
    description: String!
    version: String!
    dependencies: [ScriptDependencyInput]
    category: Category!
    platform: [ScriptPlatformInput]
    execute: AssetContentMutationInput!
    readme: AssetContentMutationInput!
    superuser: Boolean
    accessToken: String!
}

# NOTIFICATIONS

input SubscriptionQueryInput {
    accessToken: String!
}

type Subscription {
    topic: String!
    endpoint: String!
    expiration: Int!
}

# ACTIVITIES


enum ExecutionReportStatus {
    SUCCESSFUL
    FAILED
}

input ExecutionReportInput {
    name: String!
    namespace: String
    version: String!
    status: ExecutionReportStatus!
}

input ActivitiesQueryInput {
    id: String!
}

type Activity {
    datetime: String!
    type: String!
    value: String!
}

# CATEGORY

enum Category {
    INSTALLER
    UTILITY
    FIX
}

# SEARCH

input SearchQueryInput {
    term: String!
    category: Category
    platform: ScriptPlatformInput
}

type SearchResultItem {
    name: String!
    namespace: String
    description: String!
    category: Category!
    version: String!
    stats: PackageActivitiesStats!
}

type SearchResult {
    items: [SearchResultItem]
    queryTime: Int!
}

# PLATFORM

type PlatformRelease {
    codename: String!
    dockerImage: String!
}

type Platform {
    icon: AssetContent!
    os: String!
    dist: String!
    releases: [PlatformRelease]
}

# QUERY & MUTATION

type Query {
    search(input: SearchQueryInput!): SearchResult
    package(input: PackageQueryInput!): Package
    activities(input: ActivitiesQueryInput!): [Activity]
    asset(input: AssetContentQueryInput!): AssetContent!
    userPackages(input: UserPackagesQueryInput!): [PackageMetadata]
    script(input: ScriptQueryInput!): Script
    scriptMetadata(input: ScriptVersionsQueryInput!): [ScriptMetadata!]
    userAccessToken(input: UserAccessTokenQueryInput!): UserAccessResponse
    subscription(input: SubscriptionQueryInput!): Subscription
    platforms: [Platform]
}

# @Todo: Mutation processes are asynchronous, use subcriptions to watch the results.

type Mutation {
    createAsset(input: AssetContentMutationInput!): Asset!
    publish(input: PublishMutationInput!): Boolean!
    userSignUp(input: UserSignUpMutationInput!): UserSignUpResponse
    userConfirmSignUp(input: UserConfirmSignUpInput!): Boolean
    userNewPassword(input: UserSetNewPasswordInput!): UserAccessResponse
    userRefreshAccessToken(
        input: UserRefreshAccessTokenInput!
    ): UserAccessResponse
    executionReport(input: ExecutionReportInput!): Boolean!
}
