syntax = "proto3";
package anytype.model;
option go_package = "pkg/lib/pb/model";

import "google/protobuf/struct.proto";

message SmartBlockSnapshotBase {
    repeated Block blocks = 1;
    google.protobuf.Struct details = 2;
    google.protobuf.Struct fileKeys = 3 [deprecated=true];
    repeated Relation extraRelations = 4 [deprecated=true];
    repeated string objectTypes = 5;
    google.protobuf.Struct collections = 6;
    repeated string removedCollectionKeys = 8;
    repeated RelationLink relationLinks = 7;
    string key = 9; // only used for pb backup purposes, ignored in other cases
    int64 originalCreatedTimestamp = 10; // ignored in import/export in favor of createdDate relation. Used to store original user-side object creation timestamp
    FileInfo fileInfo = 11;
}

enum SmartBlockType {
    AccountOld = 0; // deprecated

    Page = 0x10;
    ProfilePage = 0x11;
    Home = 0x20;
    Archive = 0x30;
    Widget = 0x70;

    File = 0x100;

    Template = 0x120;
    BundledTemplate = 0x121;

    BundledRelation = 0x200; // DEPRECATED
    SubObject = 0x201;
    BundledObjectType = 0x202;    // DEPRECATED
    AnytypeProfile = 0x203;
    Date = 0x204;
    Workspace = 0x206;
    STRelation = 0x209;
    STType = 0x210;
    STRelationOption = 0x211;
    SpaceView = 0x212;

    Identity = 0x214;
    Participant = 0x216;
    MissingObject = 0x207;

    FileObject = 0x215;

    NotificationObject = 0x217;
    DevicesObject = 0x218;
    ChatObject = 0x219; // Container for any-store based chats
    ChatDerivedObject = 0x220; // Any-store based object for chat
    AccountObject = 0x221; // Container for account data in tech space
}

message Search {
    message Result {
        string objectId = 1;
        google.protobuf.Struct details = 2; //
        repeated Meta meta = 3; // meta information about the search result
    }

    message Meta {
        string highlight = 1; // truncated text with highlights
        repeated Range highlightRanges = 2; // ranges of the highlight in the text (using utf-16 runes)
        string blockId = 3; // block id where the highlight has been found
        string relationKey = 4; // relation key of the block where the highlight has been found
        google.protobuf.Struct relationDetails = 5; // contains details for dependent object. E.g. relation option or type. todo: rename to dependantDetails
    }
}

message Block {
    string id = 1;
    google.protobuf.Struct fields = 2;
    Restrictions restrictions = 3;
    repeated string childrenIds = 4;
    string backgroundColor = 5;
    Align align = 6;
    VerticalAlign verticalAlign = 7;

    oneof content {
        Content.Smartblock smartblock = 11;

        Content.Text text = 14;
        Content.File file = 15;
        Content.Layout layout = 16;
        Content.Div div = 17;
        Content.Bookmark bookmark = 18;
        Content.Icon icon = 19;
        Content.Link link = 20;
        Content.Dataview dataview = 21;
        Content.Relation relation = 22;
        Content.FeaturedRelations featuredRelations = 23;
        Content.Latex latex = 24;
        Content.TableOfContents tableOfContents = 25;
        Content.Table table = 26;
        Content.TableColumn tableColumn = 27;
        Content.TableRow tableRow = 28;
        Content.Widget widget = 29;
        Content.Chat chat = 30;
    }

    message Restrictions {
        bool read = 1;
        bool edit = 2;
        bool remove = 3;
        bool drag = 4;
        bool dropOn = 5;
    }

    enum Position {
        None = 0;
        // above target block
        Top = 1;
        // under target block
        Bottom = 2;
        // to left of target block
        Left = 3;
        // to right of target block
        Right = 4;
        // inside target block, as last block
        Inner = 5;
        // replace target block
        Replace = 6;
        // inside target block, as first block
        InnerFirst = 7;
    }

    enum Align {
        AlignLeft = 0;
        AlignCenter = 1;
        AlignRight = 2;
        AlignJustify = 3;
    }

    enum VerticalAlign {
        VerticalAlignTop = 0;
        VerticalAlignMiddle = 1;
        VerticalAlignBottom = 2;
    }

    message Content {
        /*
        * Layout have no visual representation, but affects on blocks, that it contains.
        * Row/Column layout blocks creates only automatically, after some of a D&D operations, for example
        */
        message Layout {
            Style style = 1;

            enum Style {
                Row = 0;
                Column = 1;
                Div = 2;
                Header = 3;
                TableRows = 4;
                TableColumns = 5;
            }
        }

        /*
        * Link: block to link some content from an external sources.
        */
        message Link {
            string targetBlockId = 1; // id of the target block
            Style style = 2; // deprecated
            google.protobuf.Struct fields = 3;
            IconSize iconSize = 4;
            CardStyle cardStyle = 5;
            Description description = 6;
            repeated string relations = 7;

            enum IconSize {
                SizeNone = 0;
                SizeSmall = 1;
                SizeMedium = 2;
            }

            enum Style {
                Page = 0;
                Dataview = 1;
                Dashboard = 2;
                Archive = 3;
                // ...
            }

            enum Description {
                None = 0;
                Added = 1;
                Content = 2;
            }

            enum CardStyle {
                Text = 0;
                Card = 1;
                Inline = 2;
            }
        }

        /*
        * Divider: block, that contains only one horizontal thin line
        */
        message Div {
            Style style = 1;

            enum Style {
                Line = 0;
                Dots = 1;
            }
        }

        /*
        * Bookmark is to keep a web-link and to preview a content.
        */
        message Bookmark {
            string url = 1;
            // Deprecated. Get this data from the target object.
            string title = 2;
            // Deprecated. Get this data from the target object.
            string description = 3;
            // Deprecated. Get this data from the target object.
            string imageHash = 4;
            // Deprecated. Get this data from the target object.
            string faviconHash = 5;

            LinkPreview.Type type = 6;
            string targetObjectId = 7;

            State state = 8;

            enum State {
                Empty = 0;
                Fetching = 1;
                Done = 2;
                Error = 3;
            }
        }

        message Icon {
            string name = 1;
        }

        message FeaturedRelations {
        }

        message Text {
            string text = 1;
            Style style = 2;
            Marks marks = 3; // list of marks to apply to the text
            bool checked = 4;
            string color = 5;
            string iconEmoji = 6; // used with style Callout
            string iconImage = 7; // in case both image and emoji are set, image should has a priority in the UI

            message Marks {
                repeated Mark marks = 1;
            }

            message Mark {
                Range range = 1; // range of symbols to apply this mark. From(symbol) To(symbol)
                Type type = 2;
                string param = 3; // link, color, etc

                enum Type {
                    Strikethrough = 0;
                    Keyboard = 1;
                    Italic = 2;
                    Bold = 3;
                    Underscored = 4;
                    Link = 5;
                    TextColor = 6;
                    BackgroundColor = 7;
                    Mention = 8;
                    Emoji = 9;
                    Object = 10;
                }
            }

            enum Style {
                Paragraph = 0;
                Header1 = 1;
                Header2 = 2;
                Header3 = 3;
                Header4 = 4; // deprecated
                Quote = 5;
                Code = 6;
                Title = 7; // currently only one block of this style can exists on a page
                Checkbox = 8;
                Marked = 9;
                Numbered = 10;
                Toggle = 11;
                Description = 12; // currently only one block of this style can exists on a page
                Callout = 13;

            }
        }

        message File {
            string hash = 1;
            string name = 2;
            Type type = 3;
            string mime = 4;
            int64 size = 5;
            int64 addedAt = 6;
            string targetObjectId = 9;

            State state = 7;
            Style style = 8;

            enum Type {
                None = 0;
                File = 1;
                Image = 2;
                Video = 3;
                Audio = 4;
                PDF = 5;
            }

            enum Style {
                Auto = 0; // all types expect File and None has Embed style by default
                Link = 1;
                Embed = 2;
            }

            enum State {
                Empty = 0; // There is no file and preview, it's an empty block, that waits files.
                Uploading = 1; // There is still no file/preview, but file already uploading
                Done = 2; // File and preview downloaded
                Error = 3; // Error while uploading
            }
        }

        message Smartblock {
        }

        message Dataview {
            repeated string source = 1; // can be set for detached(without TargetObjectId) inline sets
            repeated View views = 2;
            string activeView = 3; // do not generate changes for this field
            // deprecated
            repeated model.Relation relations = 4;
            repeated GroupOrder groupOrders = 12;
            repeated ObjectOrder objectOrders = 13;
            repeated anytype.model.RelationLink relationLinks = 5;
            string TargetObjectId = 6; // empty for original set/collection objects and for detached inline sets
            bool isCollection = 14;

            message View {
                string id = 1;
                Type type = 2;
                string name = 3;
                repeated Sort sorts = 4;
                repeated Filter filters = 5;
                repeated Relation relations = 6; // relations fields/columns options, also used to provide the order
                string coverRelationKey = 7; // Relation used for cover in gallery
                bool hideIcon = 8; // Hide icon near name
                Size cardSize = 9; // Gallery card size
                bool coverFit = 10; // Image fits container
                string groupRelationKey = 11; // Group view by this relationKey
                bool groupBackgroundColors = 12; // Enable backgrounds in groups
                int32 pageLimit = 13; // Limit of objects shown in widget
                string defaultTemplateId = 14; // Default template that is chosen for new object created within the view
                string defaultObjectTypeId = 15; // Default object type that is chosen for new object created within the view

                enum Type {
                    Table = 0;
                    List = 1;
                    Gallery = 2;
                    Kanban = 3;
                    Calendar = 4;
                    Graph = 5;
                }

                enum Size {
                    Small = 0;
                    Medium = 1;
                    Large = 2;
                }
            }

            message Relation {
                string key = 1;
                bool isVisible = 2;
                int32 width = 3; // the displayed column % calculated based on other visible relations
                // bool isReadOnly = 4; // deprecated

                bool dateIncludeTime = 5;
                TimeFormat timeFormat = 6;
                DateFormat dateFormat = 7;
                FormulaType formula = 8;
                Block.Align align = 9;

                enum DateFormat {
                    MonthAbbrBeforeDay = 0; // Jul 30, 2020
                    MonthAbbrAfterDay = 1; // 30 Jul 2020
                    Short = 2; // 30/07/2020
                    ShortUS = 3; // 07/30/2020
                    ISO = 4; // 2020-07-30
                }

                enum TimeFormat {
                    Format12 = 0;
                    Format24 = 1;
                }

                enum FormulaType {
                    None				    = 0;
                    Count				    = 1;
                    CountValue      = 2;
                    CountDistinct		= 3;
                    CountEmpty			= 4;
                    CountNotEmpty		= 5;
                    PercentEmpty		= 6;
                    PercentNotEmpty	= 7;
                    MathSum				  = 8;
                    MathAverage			= 9;
                    MathMedian			= 10;
                    MathMin				  = 11;
                    MathMax				  = 12;
                    Range				    = 13;
                }
            }

            message Sort {
                string RelationKey = 1;
                Type type = 2;
                repeated google.protobuf.Value customOrder = 3;
                RelationFormat format = 4;
                bool includeTime = 5;
                string id = 6;
                EmptyType emptyPlacement = 7;
                bool noCollate = 8;

                enum Type {
                    Asc = 0;
                    Desc = 1;
                    Custom = 2;
                }

                enum EmptyType {
                    NotSpecified = 0;
                    Start = 1;
                    End = 2;
                }
            }

            message Filter {
                string id = 9;
                Operator operator = 1; // looks not applicable?
                string RelationKey = 2;
                string relationProperty = 5;
                Condition condition = 3;
                google.protobuf.Value value = 4;
                QuickOption quickOption = 6;
                RelationFormat format = 7;
                bool includeTime = 8;
                repeated Filter nestedFilters = 10;

                enum Operator {
                    No = 0;
                    Or = 1;
                    And = 2;
                }

                enum Condition {
                    None = 0;
                    Equal = 1;
                    NotEqual = 2;
                    Greater = 3;
                    Less = 4;
                    GreaterOrEqual = 5;
                    LessOrEqual = 6;
                    Like = 7;
                    NotLike = 8;
                    In = 9; // "at least one value(from the provided list) is IN"
                    NotIn = 10; // "none of provided values are IN"
                    Empty = 11;
                    NotEmpty = 12;
                    AllIn = 13;
                    NotAllIn = 14;
                    ExactIn = 15;
                    NotExactIn = 16;
                    Exists = 17;
                }

                enum QuickOption {
                    ExactDate = 0;
                    Yesterday = 1;
                    Today = 2;
                    Tomorrow = 3;
                    LastWeek = 4;
                    CurrentWeek = 5;
                    NextWeek = 6;
                    LastMonth = 7;
                    CurrentMonth = 8;
                    NextMonth = 9;
                    NumberOfDaysAgo = 10;
                    NumberOfDaysNow = 11;
                }
            }

            message GroupOrder {
                string viewId = 1;
                repeated ViewGroup viewGroups = 2;
            }

            message ViewGroup {
                string groupId = 1;
                int32 index = 2;
                bool hidden = 3;
                string backgroundColor = 4;
            }

            message ObjectOrder {
                string viewId = 1;
                string groupId = 2;
                repeated string objectIds = 3;
            }

            message Group {
                string id = 1;
                oneof Value {
                    Status status = 2;
                    Tag tag = 3;
                    Checkbox checkbox = 4;
                    Date date = 5;
                }
            }

            message Status {
                string id = 1;
            }

            message Tag {
                repeated string ids = 1;
            }

            message Checkbox {
                bool checked = 1;
            }

            message Date {
            }
        }

        message Relation {
            string key = 1;
        }

        message Latex {
            string text = 1;
            Processor processor = 2;

            enum Processor {
                Latex = 0;
                Mermaid = 1;
                Chart = 2;
                Youtube = 3;
                Vimeo = 4;
                Soundcloud = 5;
                GoogleMaps = 6;
                Miro = 7;
                Figma = 8;
                Twitter = 9;
                OpenStreetMap = 10;
                Reddit = 11;
                Facebook = 12;
                Instagram = 13;
                Telegram = 14;
                GithubGist = 15;
                Codepen = 16;
                Bilibili = 17;
                Excalidraw = 18;
                Kroki = 19;
                Graphviz = 20;
                Sketchfab = 21;
                Image = 22;
            }
        }

        message TableOfContents {
        }

        message Table {}
        message TableColumn {}
        message TableRow {
            bool isHeader = 1;
        }

        message Widget {
            Layout layout = 1;
            int32 limit = 2;
            string viewId = 3;
            bool autoAdded = 4;

            enum Layout {
                Link = 0;
                Tree = 1;
                List = 2;
                CompactList = 3;
                View = 4;
            }
        }
        message Chat {

        }
    }
}

/*
* Used to decode block meta only, without the content itself
*/
message BlockMetaOnly {
    string id = 1;
    google.protobuf.Struct fields = 2;
}

/*
* General purpose structure, uses in Mark.
*/
message Range {
    int32 from = 1;
    int32 to = 2;
}

/**
* Contains basic information about a user account
*/
message Account {
    string id = 1; // User's thread id
    Config config = 4;
    Status status = 5;
    Info info = 6;

    message Config {
        bool enableDataview = 1;
        bool enableDebug = 2;
        bool enablePrereleaseChannel = 3;
        bool enableSpaces = 4;

        google.protobuf.Struct extra = 100;
    }

    message Status {
        StatusType statusType = 1;
        int64 deletionDate = 2;
    }

    enum StatusType {
        Active = 0;
        PendingDeletion = 1;
        StartedDeletion = 2;
        Deleted = 3;
    }

    message Info {
        string homeObjectId = 2; // home dashboard block id
        string archiveObjectId = 3; // archive block id
        string profileObjectId = 4; // profile block id
        string marketplaceWorkspaceId = 11; // marketplace workspace id
        string workspaceObjectId = 15; // workspace object id. used for space-level chat

        string deviceId = 8;
        string accountSpaceId = 9; // the first created private space. It's filled only when account is created
        string widgetsId = 10;
        string spaceViewId = 13;
        string techSpaceId = 14;

        string gatewayUrl = 101; // gateway url for fetching static files
        string localStoragePath = 103; // path to local storage
        string timeZone = 104; // time zone from config
        string analyticsId = 105;
        string networkId = 106; // network id to which anytype is connected
        string ethereumAddress = 107; // we have Any PK AND Ethereum PK derived from one seed phrase
    }

    message Auth {
        enum LocalApiScope {
            Limited = 0; // Used in WebClipper; AccountSelect(to be deprecated), ObjectSearch, ObjectShow, ObjectCreate, ObjectCreateFromURL, BlockPreview, BlockPaste, BroadcastPayloadEvent
            JsonAPI = 1; // JSON API only, no direct grpc api calls allowed
            Full = 2; // Full access, not available via LocalLink
        }
    }

}

message LinkPreview {
    string url = 1;
    string title = 2;
    string description = 3;
    string imageUrl = 4;
    string faviconUrl = 5;
    Type type = 6;

    enum Type {
        Unknown = 0;
        Page = 1;
        Image = 2;
        Text = 3;
    }
}

message Restrictions {
    repeated ObjectRestriction object = 1;
    repeated DataviewRestrictions dataview = 2;

    enum ObjectRestriction {
        None = 0;
        // restricts delete
        Delete = 1;
        // restricts work with relations
        Relations = 2;
        // restricts work with blocks
        Blocks = 3;
        // restricts work with details
        Details = 4;
        // restricts type changing
        TypeChange = 5;
        // restricts layout changing
        LayoutChange = 6;
        // restricts template creation from this object
        Template = 7;
        // restricts duplicate object
        Duplicate = 8;
        // can be set only for types. Restricts creating objects of this type
        CreateObjectOfThisType = 9;
        // object is not allowed to publish
        Publish = 10;
    }


    message DataviewRestrictions {
        string blockId = 1;
        repeated DataviewRestriction restrictions = 2;
    }

    enum DataviewRestriction {
        DVNone = 0;
        DVRelation = 1;
        DVCreateObject = 2;
        DVViews = 3;
    }
}

message Object {
    message ChangePayload {
        SmartBlockType smartBlockType = 1;
        string key = 2;
        bytes data = 3;
    }
}

message SpaceObjectHeader {
    string spaceID = 1;
}

message ObjectType {
    string url = 1; // leave empty in case you want to create the new one
    string name = 2; // name of objectType in singular form (can be localized for bundled types)
    repeated RelationLink relationLinks = 3; // cannot contain more than one Relation with the same RelationType
    Layout layout = 4;
    string iconEmoji = 5; // emoji symbol
    string description = 6;
    bool hidden = 7;
    bool readonly = 10;
    repeated SmartBlockType types = 8;
    bool isArchived = 9; // sets locally to hide object type from set and some other places
    bool installedByDefault = 11;
    string key = 12; // name of objectType (can be localized for bundled types)
    int64 revision = 13; // revision of system objectType. Used to check if we should change type content or not
    bool restrictObjectCreation = 14; // restricts creating objects of this type for users
    int64 iconColor = 15; // color of object type icon
    string iconName = 16; // name of object type icon
    string pluralName = 17; // name of objectType in plural form (can be localized for bundled types)

    enum Layout {
        basic = 0;
        profile = 1;
        todo = 2;
        set = 3;
        objectType = 4;
        relation = 5;
        file = 6;
        dashboard = 7;
        image = 8;
        note = 9;
        space = 10;
        bookmark = 11;
        relationOptionsList = 12;
        relationOption = 13;
        collection = 14;
        audio = 15;
        video = 16;
        date = 17;
        spaceView = 18;
        participant = 19;

        pdf = 20;
        chat = 21; // deprecated
        chatDerived = 22;
        tag = 23;
    }
}

message Layout {
    ObjectType.Layout id = 1;
    string name = 2;
    repeated Relation requiredRelations = 3; // relations required for this object type
}

message RelationWithValue {
    Relation relation = 1;
    google.protobuf.Value value = 2;
}

// Relation describe the human-interpreted relation type. It may be something like "Date of creation, format=date" or "Assignee, format=objectId, objectType=person"
message Relation {
    string id = 100;

    // Key under which the value is stored in the map. Must be unique for the object type.
    // It usually auto-generated bsonid, but also may be something human-readable in case of prebuilt types.
    string key = 1;

    RelationFormat format = 2; // format of the underlying data
    string name = 3; // name to show (can be localized for bundled types)
    google.protobuf.Value defaultValue = 4;
    DataSource dataSource = 5; // where the data is stored

    bool hidden = 6; // internal, not displayed to user (e.g. coverX, coverY)
    bool readOnly = 7; // value not editable by user tobe renamed to readonlyValue
    bool readOnlyRelation = 15; // relation metadata, eg name and format is not editable by user

    bool multi = 8; // allow multiple values (stored in pb list)

    repeated string objectTypes = 9; // URL of object type, empty to allow link to any object
    // index 10, 11 was used in internal-only builds. Can be reused, but may break some test accounts
    repeated Option selectDict = 12; // default dictionary with unique values to choose for select/multiSelect format
    int32 maxCount = 13; // max number of values can be set for this relation. 0 means no limit. 1 means the value can be stored in non-repeated field
    string description = 14;

    // on-store fields, injected only locally
    Scope scope = 20; // deprecated, to be removed
    string creator = 21; // creator profile id
    int64 revision = 22; // revision of system relation. Used to check if we should change relation content or not

    message Option {
        string id = 1; // id generated automatically if omitted
        string text = 2;
        string color = 3; // stored
        // 4 is reserved for old relation format
        string relationKey = 5; // stored
    }

    enum Scope {
        object = 0; // stored within the object
        type = 1; // stored within the object type
        setOfTheSameType = 2; // aggregated from the dataview of sets of the same object type
        objectsOfTheSameType = 3; // aggregated from the dataview of sets of the same object type
        library = 4; // aggregated from relations library
    }

    enum DataSource {
        details = 0; // default, stored inside the object's details
        derived = 1; // stored locally, e.g. in badger or generated on the fly
        account = 2; // stored in the account DB. means existing only for specific anytype account
        local = 3; // stored locally
    }
}

// RelationFormat describes how the underlying data is stored in the google.protobuf.Value and how it should be validated/sanitized
enum RelationFormat {
    longtext = 0; // string
    shorttext = 1; // string, usually short enough. May be truncated in the future
    number = 2; // double
    status = 3; // string or list of string(len==1)
    tag = 11; // list of string (choose multiple from a list)
    date = 4; // float64(pb.Value doesn't have int64) or the string
    file = 5; // relation can has objects of specific types: file, image, audio, video
    checkbox = 6; // boolean
    url = 7; // string with sanity check
    email = 8; // string with sanity check
    phone = 9; // string with sanity check
    emoji = 10; // one emoji, can contains multiple utf-8 symbols

    object = 100; // relation can has objectType to specify objectType
    relations = 101; // base64-encoded relation pb model

}

enum ObjectOrigin {
  none = 0;
  clipboard = 1;
  dragAndDrop = 2;
  import = 3;
  webclipper = 4;
  sharingExtension = 5;
  usecase = 6;
  builtin = 7;
  bookmark = 8;
  api = 9;
}

message RelationLink {
    string key = 1;
    RelationFormat format = 2;
}

message Relations {
    repeated Relation relations = 1;
}

message RelationOptions {
    repeated Relation.Option options = 1;
}

message InternalFlag {
    Value value = 1;

    // Use such a weird construction due to the issue with imported repeated enum type
    // Look https://github.com/golang/protobuf/issues/1135 for more information.
    enum Value {
        editorDeleteEmpty = 0;
        editorSelectType = 1;
        editorSelectTemplate = 2;
        collectionDontIndexLinks = 3;
    }
}


/*
        * Works with a smart blocks: Page, Dashboard
        * Dashboard opened, click on a page, Rpc.Block.open, Block.ShowFullscreen(PageBlock)
*/
message ObjectView {
    string rootId = 1; // Root block id
    repeated Block blocks = 2; // dependent simple blocks (descendants)
    repeated DetailsSet details = 3; // details for the current and dependent objects
    SmartBlockType type = 4;

    message DetailsSet {
        string id = 1; // context objectId
        google.protobuf.Struct details = 2; // can not be a partial state. Should replace client details state
        repeated string subIds = 3;
    }

    message RelationWithValuePerObject {
        string objectId = 1;
        repeated RelationWithValue relations = 2;
    }

    repeated Relation relations = 7; // DEPRECATED, use relationLinks instead
    repeated RelationLink relationLinks = 10;

    Restrictions restrictions = 8; // object restrictions
    HistorySize history = 9;

    message HistorySize {
        int32 undo = 1;
        int32 redo = 2;
    }

    repeated BlockParticipant blockParticipants = 11;
    message BlockParticipant {
        string blockId = 1;
        string participantId = 2;
    }
}

enum SpaceStatus {
    // Unknown means the space is not loaded yet
    Unknown = 0;
    // Loading - the space in progress of loading
    Loading = 1;
    // Ok - the space loaded and available
    Ok = 2;
    // Missing - the space is missing
    Missing = 3;
    // Error - the space loading ended with an error
    Error = 4;

    // RemoteWaitingDeletion - network status is "waiting deletion"
    RemoteWaitingDeletion = 5;
    // RemoteDeleted - the space is deleted in the current network
    RemoteDeleted = 6;
    // SpaceDeleted - the space should be deleted in the network
    SpaceDeleted = 7;
    // SpaceActive - the space is active in the network
    SpaceActive = 8;
    // SpaceJoining - the account is joining the space
    SpaceJoining = 9;
    // SpaceRemoving - the account is removing from space or the space is removed from network
    SpaceRemoving = 10;
}

message ParticipantPermissionChange {
    string identity = 1;
    ParticipantPermissions perms = 2;
}

enum ParticipantPermissions {
    Reader = 0;
    Writer = 1;
    Owner = 2;
    NoPermissions = 3;
}

enum ParticipantStatus {
    Joining = 0;
    Active = 1;
    Removed = 2;
    Declined = 3;
    Removing = 4;
    Canceled = 5;
}

enum SpaceAccessType {
    Private = 0;
    Personal = 1;
    Shared = 2;
}

enum SpaceUxType {
    Chat = 0; // chat-first UX
    Data = 1; // objects-first UX
    Stream = 2; // stream UX (chat with limited amount of owners)
}

message Metadata {
    oneof payload {
        Payload.IdentityPayload identity = 1;
    }

    message Payload {
        message IdentityPayload {
            bytes profileSymKey = 1;
        }
    }
}

message Notification {
    string id = 1;
    int64 createTime = 2;
    Status status = 4;
    bool isLocal = 5;
    oneof payload {
        Import import = 6;
        Export export = 8;
        GalleryImport galleryImport = 9;
        RequestToJoin requestToJoin = 10;
        Test test = 11;
        ParticipantRequestApproved participantRequestApproved = 13;
        RequestToLeave requestToLeave = 15;
        ParticipantRemove participantRemove = 16;
        ParticipantRequestDecline participantRequestDecline = 17;
        ParticipantPermissionsChange participantPermissionsChange = 18;
    }
    string space = 7;
    string aclHeadId = 14;

    message Import {
        string processId = 1;
        model.Import.ErrorCode errorCode = 2;
        model.Import.Type importType = 3;
        string spaceId = 4;
        string name = 5;
        string spaceName = 6;
    }

    message Export {
        Code errorCode = 2;
        model.Export.Format exportType = 3;
        enum Code {
            NULL = 0;
            UNKNOWN_ERROR = 1;
            BAD_INPUT = 2;
        }
    }

    message GalleryImport {
        string processId = 1;
        model.Import.ErrorCode errorCode = 2;
        string spaceId = 3;
        string name = 4;
        string spaceName = 5;
    }

    message RequestToJoin {
        string spaceId = 1;
        string identity = 2;
        string identityName = 3;
        string identityIcon = 4;
        string spaceName = 5;
    }

    message Test {}

    message ParticipantRequestApproved {
        string spaceId = 1;
        ParticipantPermissions permissions = 2;
        string spaceName = 5;
    }

    message RequestToLeave {
        string spaceId = 1;
        string identity = 2;
        string identityName = 3;
        string identityIcon = 4;
        string spaceName = 5;
    }

    message ParticipantRemove {
        string identity = 1;
        string identityName = 2;
        string identityIcon = 3;
        string spaceId = 4;
        string spaceName = 5;
    }

    message ParticipantRequestDecline {
        string spaceId = 1;
        string spaceName = 3;
    }

    message ParticipantPermissionsChange {
        string spaceId = 1;
        ParticipantPermissions permissions = 2;
        string spaceName = 3;
    }

    enum Status {
        Created = 0;
        Shown = 1;
        Read = 2;
        Replied = 3;
    }

    enum ActionType {
        CLOSE = 0;
    }
}

message Export {
    enum Format {
        Markdown = 0;
        Protobuf = 1;
        JSON = 2;
        DOT = 3;
        SVG = 4;
        GRAPH_JSON = 5;
    }
}

message Import {
    enum Type {
        Notion = 0;
        Markdown = 1;
        External = 2; // external developers use it
        Pb = 3;
        Html = 4;
        Txt = 5;
        Csv = 6;
    }

    enum ErrorCode {
      NULL = 0;
      UNKNOWN_ERROR = 1;
      BAD_INPUT = 2;
      INTERNAL_ERROR = 3;
      FILE_LOAD_ERROR = 8;
      IMPORT_IS_CANCELED = 6;

      NOTION_NO_OBJECTS_IN_INTEGRATION= 5;
      NOTION_SERVER_IS_UNAVAILABLE = 12;
      NOTION_RATE_LIMIT_EXCEEDED= 13;

      FILE_IMPORT_NO_OBJECTS_IN_ZIP_ARCHIVE = 14;
      FILE_IMPORT_NO_OBJECTS_IN_DIRECTORY = 17;

      HTML_WRONG_HTML_STRUCTURE = 10;

      PB_NOT_ANYBLOCK_FORMAT = 11;

      CSV_LIMIT_OF_ROWS_OR_RELATIONS_EXCEEDED = 7;

      INSUFFICIENT_PERMISSIONS = 9;
    }
}

message Invite {
    bytes payload = 1;
    bytes signature = 2;
}

message InvitePayload {
    string creatorIdentity = 1;
    string creatorName = 2;
    bytes aclKey = 3;
    string spaceId = 4;
    string spaceName = 5;
    string spaceIconCid = 6;
    repeated FileEncryptionKey spaceIconEncryptionKeys = 7;

    InviteType inviteType = 8;
    bytes guestKey = 9;
    enum InviteType {
        JoinAsMember = 0; // aclKey contains the key to sign the ACL record
        JoinAsGuest = 1; // guestKey contains the privateKey of the guest user
    }
}

message IdentityProfile {
    string identity = 1;
    string name = 2;
    string iconCid = 3;
    repeated FileEncryptionKey iconEncryptionKeys = 4;
    string description = 5;
    string globalName = 6;
}

message FileInfo {
    string fileId = 1;
    repeated FileEncryptionKey encryptionKeys = 2;
}

message FileEncryptionKey {
  string path = 1;
  string key = 2;
}

enum ImageKind {
    Basic = 0;
    Cover = 1;
    Icon = 2;
    AutomaticallyAdded = 3;
}

enum FileIndexingStatus {
    NotIndexed = 0;
    Indexed = 1;
    NotFound = 2;
}

enum SpaceShareableStatus {
    StatusUnknown = 0;
    StatusShareable = 1;
    StatusNotShareable = 2;
}

message ManifestInfo {
    string schema = 1;
    string id = 2;
    string name = 3;
    string author = 4;
    string license = 5;
    string title = 6;
    string description = 7;
    repeated string screenshots = 8;
    string downloadLink = 9;
    int32 fileSize = 10;
    repeated string categories = 11;
    string language = 12;
}

enum NameserviceNameType {
    // .any suffix
    AnyName = 0;
}


message Membership {
    enum Status {
        StatusUnknown = 0;
        // please wait a bit more, we are still processing your request
        // the payment is confirmed, but we need more time to do some side-effects:
        // - increase limits
        // - send emails
        // - allocate names
        StatusPending = 1;
        // the membership is active, ready to use!
        StatusActive = 2;
        // in some cases we need to finalize the process:
        // - if user has bought membership directly without first calling
        // the BuySubscription method
        // in this case please call Finalize to finish the process
        StatusPendingRequiresFinalization = 3;
    }

    enum PaymentMethod {
        MethodNone = 0;
        MethodStripe = 1;
        MethodCrypto = 2;
        MethodInappApple = 3;
        MethodInappGoogle = 4;
    }

    enum EmailVerificationStatus {
        // user NEVER comleted the verification of the email
        StatusNotVerified = 0;
        // user has asked for new code, but did not enter it yet
        // (even if email was verified before, you can ask to UPDATE your e-mail)
        // please wait, you can not ask for more codes yet
        StatusCodeSent = 1;
        // the e-mail is finally verified
        StatusVerified = 2;
    }

    // it was Tier before, changed to int32 to allow dynamic values
    uint32 tier = 1;
    Status status = 2;
    uint64 dateStarted = 3;
    uint64 dateEnds = 4;
    bool isAutoRenew = 5;
    PaymentMethod paymentMethod = 6;
    // can be empty if user did not ask for any name
    string nsName = 7;
    anytype.model.NameserviceNameType nsNameType = 8;
    // if the email was verified by the user or set during the checkout - it will be here
    string userEmail = 9;
    bool subscribeToNewsletter = 10;
}

message MembershipTierData {
    enum PeriodType {
        PeriodTypeUnknown = 0;
        PeriodTypeUnlimited = 1;
        PeriodTypeDays = 2;
        PeriodTypeWeeks = 3;
        PeriodTypeMonths = 4;
        PeriodTypeYears = 5;
    }

    // this is a unique Payment Node ID of the tier
    // WARNING: tiers can be sorted differently, not according to their IDs!
    uint32 id = 1;
    // localazied name of the tier
    string name = 2;
    // just a short technical description
    string description = 3;
    // is this tier for testing and debugging only?
    bool isTest = 4;
    // how long is the period of the subscription
    PeriodType periodType = 5;
    // i.e. "5 days" or "3 years"
    uint32 periodValue = 6;
    // this one is a price we use ONLY on Stripe platform
    uint32 priceStripeUsdCents = 7;
    // number of ANY NS names that this tier includes
    // also in the "features" list (see below)
    uint32 anyNamesCountIncluded = 8;
    // somename.any - is of len 8
    uint32 anyNameMinLength = 9;
    // localized strings for the features
    repeated string features = 10;
    // green, blue, red, purple, custom
    string colorStr = 11;

    // Stripe platform-specific data:
    string stripeProductId = 12;
    string stripeManageUrl = 13;

    // iOS platform-specific data:
    string iosProductId = 15;
    string iosManageUrl = 16;

    // Android platform-specific data:
    string androidProductId = 17;
    string androidManageUrl = 18;

    // "limited offer" or somehing like that
    string offer = 19;
}

enum DeviceNetworkType {
    WIFI = 0;
    CELLULAR = 1;
    NOT_CONNECTED = 2;
}

message Detail {
    string key = 1;
    google.protobuf.Value value = 2; // NUll - removes key
}

message DeviceInfo {
    string id = 1;
    string name = 2;
    int64 addDate = 3;
    bool archived = 4;
    bool isConnected = 5;
}

message ChatState {
    message UnreadState {
        string oldestOrderId = 1; // oldest(in the lex sorting) unread message order id. Client should ALWAYS scroll through unread messages from the oldest to the newest
        int32 counter = 2; // total number of unread messages
    }
    UnreadState messages = 1; // unread messages
    UnreadState mentions = 2; // unread mentions
    string lastStateId = 3; // reflects the state of the chat db at the moment of sending response/event that includes this state
}

message ChatMessage {
    string id = 1;        // Unique message identifier
    string orderId = 2;   // Lexicographical id for message in order of tree traversal
    string creator = 3;       // Identifier for the message creator
    int64 createdAt = 4;
    int64 modifiedAt = 9;

    // stateId is ever-increasing id (BSON ObjectId) for this message. Unlike orderId, this ID is ordered by the time messages are added. For example, it's useful to prevent accidental reading of messages from the past when a ChatReadMessages request is sent: a message from the past may appear, but the client is still unaware of it
    string stateId = 11;

    string replyToMessageId = 5;   // Identifier for the message being replied to
    MessageContent message = 6;  // Message content
    repeated Attachment attachments = 7;  // Attachments slice
    Reactions reactions = 8;  // Reactions to the message
    bool read = 10; // Message read status
    bool mentionRead = 12;
    message MessageContent {
        string text = 1;      // The text content of the message part
        Block.Content.Text.Style style = 2;    // The style/type of the message part
        repeated Block.Content.Text.Mark marks = 3; // List of marks applied to the text
    }

    message Attachment {
        string target = 1;       // Identifier for the attachment object
        AttachmentType type = 2; // Type of attachment

        enum AttachmentType {
            FILE = 0;   // File attachment
            IMAGE = 1;  // Image attachment
            LINK = 2;   // Link attachment
        }
    }

    message Reactions {
        map<string, IdentityList> reactions = 1; // Map of emoji to list of user IDs

        message IdentityList {
            repeated string ids = 1; // List of user IDs
        }
    }
}
