// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

syntax = "proto3";

package feedstore;

import "components/feed/core/proto/v2/wire/content_id.proto";
import "components/feed/core/proto/v2/wire/feed_action.proto";

option optimize_for = LITE_RUNTIME;

// Actual data stored by the client.
// This data is sourced from the wire protocol, which is converted upon receipt.
// This would replace both Journal and Content stores.
//
// This is the 'value' in the key/value store.
// Keys are defined as:
// 'S/<stream-id>' -> stream_data
// 'T/<stream-id>/<sequence-number>' -> stream_structures
// 'c/<content-id>' -> content
// 'a/<id>' -> action
// 's/<content-id>' -> shared_state
// 'N' -> next_stream_state
message Record {
  oneof data {
    StreamData stream_data = 1;
    StreamStructureSet stream_structures = 2;
    Content content = 3;
    StoredAction local_action = 4;
    StreamSharedState shared_state = 5;
    // The result of a background refresh, to be processed later.
    StreamAndContentState next_stream_state = 6;
  }
}

// Data about the Feed stream. There is at most one instance of StreamData.
message StreamData {
  // Root ContentId, as provided by the server.
  feedwire.ContentId content_id = 1;
  // Token used to request a 'more' request to the server.
  bytes next_page_token = 2;
  // Token used to read or write to the same storage.
  bytes consistency_token = 3;
  // The unix timestamp in milliseconds that the most recent content was added.
  int64 last_added_time_millis = 4;
  // Next sequential ID to be used for StoredAction.id.
  int32 next_action_id = 5;
  // The content ID of the shared state for this stream.
  feedwire.ContentId shared_state_id = 6;
}

// A set of StreamStructures that should be applied to a stream.
message StreamStructureSet {
  string stream_id = 1;
  int32 sequence_number = 2;
  repeated StreamStructure structures = 3;
}

// This is the structure of the stream.  It is defined through the parent/child
// relationship and an operation.  This message will be journaled.  Reading
// the journal from start to end will fully define the structure of the stream.
message StreamStructure {
  // The defined set of DataOperations
  // These operations align with the Operation enum defined in
  // data_operation.proto.
  enum Operation {
    UNKNOWN = 0;
    // Clear all the content in the session, creating a new session
    CLEAR_ALL = 1;
    // Append if not present or update
    UPDATE_OR_APPEND = 2;
    // Remove the node from its parent
    REMOVE = 3;
  }
  Operation operation = 1;
  // The ContentId of the content.
  feedwire.ContentId content_id = 2;
  // The parent ContentId, or unset if this is the root.
  feedwire.ContentId parent_id = 3;

  // Type of node as denoted by the server. This type has no meaning for the
  // client.
  enum Type {
    // Default type for operations that don't affect the stream (e.g. operations
    // on shared states).
    UNKNOWN_TYPE = 0;
    // The root of the stream.
    STREAM = 1;
    // An internal tree node, which may have children.
    CARD = 2;
    // A leaf node, which provides content.
    CONTENT = 3;
    // An internal tree node, which may have children.
    CLUSTER = 4;
  }
  Type type = 4;
  // Set iff type=CONTENT
  ContentInfo content_info = 5;
}

message DataOperation {
  StreamStructure structure = 1;
  // Provided if structure adds content.
  Content content = 2;
}

message RepresentationData {
  // URI (usually a URL) of what the content links to
  string uri = 1;
  // Unix timestamp (seconds) when content was published
  int64 published_time_seconds = 2;
}

message ContentInfo {
  // Score given by server.
  float score = 1;
  // Unix timestamp (seconds) that content was received by Chrome.
  int64 availability_time_seconds = 2;
  RepresentationData representation_data = 3;
  OfflineMetadata offline_metadata = 4;
}

message OfflineMetadata {
  // Title of the content.
  string title = 1;

  // Url for image for the content.
  string image_url = 2;

  // Publisher of the content.
  string publisher = 3;

  // Url for the favicon for the content.
  string favicon_url = 4;

  // Short string from the content, typically the start of an article.
  string snippet = 5;
}

message Content {
  feedwire.ContentId content_id = 1;
  // Opaque content. The UI layer knows how to parse and render this as a slice.
  bytes frame = 2;
}

// This represents a shared state item.
message StreamSharedState {
  feedwire.ContentId content_id = 1;
  // Opaque data required to render content.
  bytes shared_state_data = 2;
}

// A stored action awaiting upload.
message StoredAction {
  // Unique ID for this stored action, provided by the client.
  // This is a sequential number, so that the action with the lowest id value
  // was recorded chronologically first.
  int32 id = 1;
  // How many times we have tried to upload the action.
  int32 upload_attempt_count = 2;
  // The action to upload.
  feedwire.FeedAction action = 3;
}

// The internal version of the server response. Includes feature tree and
// content.
message StreamAndContentState {
  StreamData stream_data = 1;
  repeated Content content = 2;
  repeated StreamSharedState shared_state = 3;
}
