// Copyright 2011 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Author: abliss@google.com (Adam Bliss)

// Protobuf to encapsulate custom metadata about a resource (not including real
// HTTP Headers).

syntax = "proto2";

import "net/instaweb/spriter/public/image_spriter.proto";

option optimize_for = LITE_RUNTIME;

package net_instaweb;

message ImageDim {
  optional int32 width = 1 [ default = -1 ];
  optional int32 height = 2 [ default = -1 ];
};

// Info about the input resource that was used to create a CachedResult.
message InputInfo {
  // Generally, URLs of inputs are not kept in the protobufs, only the indices.
  // The intended usage is the URLs of inputs will be used to construct
  // the key to a cache entry, and the cache value will be an
  // encoded OutputPartitions.
  //
  // One caveat to this is that in case of a file-loaded input we store its
  // filename. This is because it's otherwise too hard to determine the name
  // when we need to do cache validation of things like nested
  // rewrites, and to keep this information accurate across caching
  // of such inner jobs.
  optional int32 index = 1;

  // This type affects how we check that CachedResults are up-to-date.
  enum Type {
    // Cached resources are valid until the expiration_time_ms.
    CACHED = 1;
    // File based resources are valid as long as the file has not changed.
    // We stat the file and compare it's mtime to last_modified_time_ms
    // to decide if the file has changed or not.
    FILE_BASED = 2;
    // E.g. data: URL resources never expire or change.
    ALWAYS_VALID = 3;
  }
  required Type type = 2;
  // An identifying timestamp which can be used to decide if a resource has
  // been updated or not. For web-based resources, we use Last-Modified headers.
  // For file-based resources, we use mtime.
  optional int64 last_modified_time_ms = 3;
  optional int64 expiration_time_ms = 4;

  // For CACHED resources, we keep track of the original fetch time so we
  // can freshen.
  optional int64 date_ms = 6;

  // For CACHED resources, we also store a hash of the input, so that we
  // we can reuse optimization results if it did not change, even if it
  // expired from the HTTP cache.
  optional string input_content_hash = 7;

  // For FILE_BASED resources, the file this was loaded from.
  optional string filename = 5;
}

// The cached result of a rewrite. This is the value of a map where the key
// is a sequence of input URLs and a filter id. The input array
// tells us which inputs are used to construct this output; it must be
// interpreted using the URL-sequence that was used to form the key.
message CachedResult {
  // Tags 1-7 are for internal use by output_resource.

  // When this is false we have previously processed the URL and have marked
  // down that we cannot do anything with it.
  optional bool optimizable = 1 [ default = true ];

  // The cached URL of this result. If this CachedResult was actually
  // fetched from the cache and is not a new one produced by
  // EnsureCachedResultCreated this will be valid if and only if
  // optimizable is true.
  optional string url = 2;

  // tags 3, 4 deleted and should not be reused.

  // Changes to custom metadata by clients done after we are written to
  // cache are lost, and it's extremely easy to get it wrong. To catch
  // mistakes like that, we mark a CachedResult as 'frozen' upon save,
  // and DCHECK any modifications.
  optional bool frozen = 5 [ default = false ];

  // If the URL is optimizable, this will contain the hash of the encoded
  // resource.
  optional string hash = 6;

  // If the URL is optimizable, this will contain the extension for the
  // encoded resource, not including the leading "."
  optional string extension = 7;

  // Tags 11+ are for use by individual filters. 8-10 have been used
  // in the past and should not be reused.

  // Dimensions of an image file, in pixels.  Used by
  // image_rewrite_filter.  Note that these dimensions are not
  // necessarily the same as the properties of the img tag,
  // represented by ResourceContext below.
  optional ImageDim image_file_dims = 11;

  // Filters that produce inlined data --- either due to inlining an external
  // resource or rewriting one that's already inline --- use this field to
  // cache either their input or the output.  In either case the raw bytes are
  // cached without any encoding.
  //
  // The input is cached in filters that have very cheap rewrites, and
  // vary the output based on things like the base URL. Output is cached
  // when the rewrite is expensive, with different base URLs being instead
  // incorporated into the key.
  optional string inlined_data = 12;

  // The result of a spriting operation, containing x/y coordinates for each
  // subimage in the sprite.
  // Used by image_combine_filter.
  optional spriter.SpriterResult spriter_result = 13;

  // Info about the input resources used to create the OutputResource that
  // this CachedResult is based off of.
  repeated InputInfo input = 14;

  // The image type is actually a net_instaweb::Image::Type.  It permits image
  // inlining to create an appropriate data: url from this and the inlined_data.
  // It's set only if inlined_data contains an image.
  optional int32 inlined_image_type = 15;

  // This contains low resolution/quality image contents. This will be set only
  // if DelayImagesFilter is enabled.
  optional string low_resolution_inlined_data = 16;

  // The image type is actually a net_instaweb::Image::Type.  It permits image
  // inlining to create an appropriate data: url from this and the
  // low_resolution_inlined_data. It's set only if low_resolution_inlined_data
  // contains an image.
  optional int32 low_resolution_inlined_image_type = 17;

  // When this is false we have previously processed the URL and marked down
  // that the resource could potentially break if its url were changed.
  optional bool url_relocatable = 18 [ default = true ];
}

// Contains the mapping of input URLs to output URLs.  In the general
// case, multiple inputs may map to multiple outputs.
//
// Consider combine_css (slightly more capable than it is today) over
// the links:
//    <link media="print"  href="p0.css"/>
//    <link media="screen" href="p1.css"/>
//    <link media="print"  href="p2.css"/>
//    <link media="screen" href="p3.css"/>
// Combining these would result in two partitions.
//    partition0 = {result="p0+p2.css", input={0,2}}
//    partition1 = {result="p1+p3.css", input={1,3}}
// Thus the CSS combiner can, as the result of one cache lookup, get
// back enough information to perform the HTML element substitutions.
//
// If this resource depends on inputs that are not mentioned in the partition
// table above (such as inputs to nested rewrites or those that failed to
// fetch properly) we add them to other_dependency to know when to invalidate.
message OutputPartitions {
  repeated CachedResult partition = 1;
  repeated InputInfo other_dependency = 2;
}

// Encapsulates all the data needed to rewrite a resource.  Any filter needing
// additional information should add it as optional fields here.
message ResourceContext {
  optional ImageDim desired_image_dims = 1;
  optional bool attempt_webp = 2 [ default = false ];
  optional bool inline_images = 3 [ default = true ];
  optional bool mobile_user_agent = 4 [ default = false ];
}
