// Copyright 2020 The Tint Authors.
//
// 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.

#ifndef SRC_READER_SPIRV_USAGE_H_
#define SRC_READER_SPIRV_USAGE_H_

#include <ostream>
#include <string>

namespace tint {
namespace reader {
namespace spirv {

/// Records the properties of a sampler or texture based on how it's used
/// by image instructions inside function bodies.
///
/// For example:
///
///   If %X is the "Image" parameter of an OpImageWrite instruction then
///    - The memory object declaration underlying %X will gain
///      AddStorageWriteTexture usage
///
///   If %Y is the "Sampled Image" parameter of an OpImageSampleDrefExplicitLod
///   instruction, and %Y is composed from sampler %YSam and image %YIm, then:
///    - The memory object declaration underlying %YSam will gain
///      AddComparisonSampler usage
///    - The memory object declaration unederlying %YIm will gain
///      AddSampledTexture and AddDepthTexture usages
class Usage {
 public:
  /// Constructor
  Usage();
  /// Copy constructor
  /// @param other the Usage to clone
  Usage(const Usage& other);
  /// Destructor
  ~Usage();

  /// @returns true if this usage is internally consistent
  bool IsValid() const;
  /// @returns true if the usage fully determines a WebGPU binding type.
  bool IsComplete() const;

  /// @returns true if this usage is a sampler usage.
  bool IsSampler() const { return is_sampler_; }
  /// @returns true if this usage is a comparison sampler usage.
  bool IsComparisonSampler() const { return is_comparison_sampler_; }

  /// @returns true if this usage is a texture usage.
  bool IsTexture() const { return is_texture_; }
  /// @returns true if this usage is a sampled texture usage.
  bool IsSampledTexture() const { return is_sampled_; }
  /// @returns true if this usage is a multisampled texture usage.
  bool IsMultisampledTexture() const { return is_multisampled_; }
  /// @returns true if this usage is a dpeth texture usage.
  bool IsDepthTexture() const { return is_depth_; }
  /// @returns true if this usage is a read-only storage texture
  bool IsStorageReadTexture() const { return is_storage_read_; }
  /// @returns true if this usage is a write-only storage texture
  bool IsStorageWriteTexture() const { return is_storage_write_; }

  /// @returns true if this is a storage texture.
  bool IsStorageTexture() const {
    return is_storage_read_ || is_storage_write_;
  }

  /// Emits this usage to the given stream
  /// @param out the output stream.
  /// @returns the modified stream.
  std::ostream& operator<<(std::ostream& out) const;

  /// Equality operator
  /// @param other the RHS of the equality test.
  /// @returns true if `other` is identical to `*this`
  bool operator==(const Usage& other) const;

  /// Adds the usages from another usage object.
  /// @param other the other usage
  void Add(const Usage& other);

  /// Records usage as a sampler.
  void AddSampler();
  /// Records usage as a comparison sampler.
  void AddComparisonSampler();

  /// Records usage as a texture of some kind.
  void AddTexture();
  /// Records usage as a read-only storage texture.
  void AddStorageReadTexture();
  /// Records usage as a write-only storage texture.
  void AddStorageWriteTexture();
  /// Records usage as a sampled texture.
  void AddSampledTexture();
  /// Records usage as a multisampled texture.
  void AddMultisampledTexture();
  /// Records usage as a depth texture.
  void AddDepthTexture();

  /// @returns this usage object as a string.
  std::string to_str() const;

 private:
  // Sampler properties.
  bool is_sampler_ = false;
  // A comparison sampler is always a sampler:
  //    |is_comparison_sampler_| implies |is_sampler_|
  bool is_comparison_sampler_ = false;

  // Texture properties.
  // |is_texture_| is always implied by any of the others below.
  bool is_texture_ = false;
  bool is_sampled_ = false;
  bool is_multisampled_ = false;  // This implies it's sampled as well.
  bool is_depth_ = false;
  bool is_storage_read_ = false;
  bool is_storage_write_ = false;
};

inline std::ostream& operator<<(std::ostream& out, const Usage& u) {
  return u.operator<<(out);
}

}  // namespace spirv
}  // namespace reader
}  // namespace tint

#endif  // SRC_READER_SPIRV_USAGE_H_
