// Copyright 2016 The Cobalt Authors. All Rights Reserved.
//
// 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 COBALT_RENDER_TREE_MOCK_RESOURCE_PROVIDER_H_
#define COBALT_RENDER_TREE_MOCK_RESOURCE_PROVIDER_H_

#include <memory>
#include <string>
#include <vector>

#include "base/memory/ref_counted.h"
#include "cobalt/render_tree/font.h"
#include "cobalt/render_tree/font_provider.h"
#include "cobalt/render_tree/glyph_buffer.h"
#include "cobalt/render_tree/image.h"
#include "cobalt/render_tree/lottie_animation.h"
#include "cobalt/render_tree/node.h"
#include "cobalt/render_tree/resource_provider.h"
#include "cobalt/render_tree/typeface.h"

#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace cobalt {
namespace render_tree {

class MockResourceProvider : public ResourceProvider {
 public:
  // Comment out override in order to enable
  // "-Winconsistent-missing-override" on Clang.  TODO: Remove this hack once
  // gmock adds override support.
  virtual base::TypeId GetTypeId() const /*override*/ {
    return base::GetTypeId<MockResourceProvider>();
  }

  MOCK_METHOD0(Finish, void());
  MOCK_METHOD1(PixelFormatSupported, bool(PixelFormat pixel_format));
  MOCK_METHOD1(AlphaFormatSupported, bool(AlphaFormat alpha_format));
  MOCK_METHOD3(AllocateImageDataMock,
               ImageData*(const math::Size& size, PixelFormat pixel_format,
                          AlphaFormat alpha_format));
  MOCK_METHOD1(CreateImageMock, Image*(ImageData* pixel_data));
  MOCK_METHOD2(AllocateRawImageMemoryMock,
               RawImageMemory*(size_t size_in_bytes, size_t alignment));
  MOCK_METHOD2(CreateMultiPlaneImageFromRawMemoryMock,
               Image*(RawImageMemory* raw_image_memory,
                      const MultiPlaneImageDataDescriptor& descriptor));
  MOCK_CONST_METHOD1(HasLocalFontFamily, bool(const char* font_family_name));
  MOCK_METHOD2(GetLocalTypefaceMock,
               Typeface*(const char* font_family_name, FontStyle font_style));
  MOCK_METHOD1(GetLocalTypefaceIfAvailableMock,
               Typeface*(const std::string& font_face_name));
  MOCK_METHOD3(GetCharacterFallbackTypefaceMock,
               Typeface*(int32 utf32_character, FontStyle font_style,
                         const std::string& language));
  MOCK_METHOD2(CreateTypefaceFromRawDataMock,
               Typeface*(RawTypefaceDataVector* raw_data,
                         std::string* error_string));
  MOCK_METHOD5(CreateGlyphBufferMock,
               render_tree::GlyphBuffer*(
                   const base::char16* text_buffer, size_t text_length,
                   const std::string& language, bool is_rtl,
                   render_tree::FontProvider* font_provider));
  MOCK_METHOD2(
      CreateGlyphBufferMock,
      render_tree::GlyphBuffer*(const std::string& utf8_string,
                                const scoped_refptr<render_tree::Font>& font));
  MOCK_METHOD6(GetTextWidth,
               float(const base::char16* text_buffer, size_t text_length,
                     const std::string& language, bool is_rtl,
                     render_tree::FontProvider* font_provider,
                     render_tree::FontVector* maybe_used_fonts));

  MOCK_METHOD2(CreateLottieAnimationMock,
               LottieAnimation*(const char* data, size_t length));

  MOCK_METHOD2(CreateMeshMock,
               render_tree::Mesh*(std::vector<render_tree::Mesh::Vertex>*,
                                  render_tree::Mesh::DrawMode));

  MOCK_METHOD1(DrawOffscreenImage,
               scoped_refptr<render_tree::Image>(
                   const scoped_refptr<render_tree::Node>& root));

  std::unique_ptr<ImageData> AllocateImageData(const math::Size& size,
                                               PixelFormat pixel_format,
                                               AlphaFormat alpha_format) {
    return std::unique_ptr<ImageData>(
        AllocateImageDataMock(size, pixel_format, alpha_format));
  }
  scoped_refptr<Image> CreateImage(std::unique_ptr<ImageData> pixel_data) {
    return scoped_refptr<Image>(CreateImageMock(pixel_data.get()));
  }

  scoped_refptr<Image> CreateImageFromSbDecodeTarget(SbDecodeTarget target) {
    return NULL;
  }

  bool SupportsSbDecodeTarget() { return false; }

  SbDecodeTargetGraphicsContextProvider*
  GetSbDecodeTargetGraphicsContextProvider() {
    return NULL;
  }

  std::unique_ptr<RawImageMemory> AllocateRawImageMemory(size_t size_in_bytes,
                                                         size_t alignment) {
    return std::unique_ptr<RawImageMemory>(
        AllocateRawImageMemoryMock(size_in_bytes, alignment));
  }
  scoped_refptr<Image> CreateMultiPlaneImageFromRawMemory(
      std::unique_ptr<RawImageMemory> raw_image_memory,
      const MultiPlaneImageDataDescriptor& descriptor) {
    return scoped_refptr<Image>(CreateMultiPlaneImageFromRawMemoryMock(
        raw_image_memory.get(), descriptor));
  }
  scoped_refptr<Typeface> GetLocalTypeface(const char* font_family_name,
                                           FontStyle font_style) {
    return scoped_refptr<Typeface>(
        GetLocalTypefaceMock(font_family_name, font_style));
  }
  scoped_refptr<Typeface> GetLocalTypefaceByFaceNameIfAvailable(
      const char* font_face_name) {
    return scoped_refptr<Typeface>(
        GetLocalTypefaceIfAvailableMock(font_face_name));
  }
  scoped_refptr<Typeface> GetCharacterFallbackTypeface(
      int32 utf32_character, FontStyle font_style,
      const std::string& language) {
    return scoped_refptr<Typeface>(GetCharacterFallbackTypefaceMock(
        utf32_character, font_style, language));
  }
  scoped_refptr<Typeface> CreateTypefaceFromRawData(
      std::unique_ptr<RawTypefaceDataVector> raw_data,
      std::string* error_string) {
    return scoped_refptr<Typeface>(
        CreateTypefaceFromRawDataMock(raw_data.get(), error_string));
  }
  scoped_refptr<render_tree::GlyphBuffer> CreateGlyphBuffer(
      const base::char16* text_buffer, size_t text_length,
      const std::string& language, bool is_rtl,
      render_tree::FontProvider* font_provider) {
    return scoped_refptr<render_tree::GlyphBuffer>(CreateGlyphBufferMock(
        text_buffer, text_length, language, is_rtl, font_provider));
  }
  scoped_refptr<render_tree::GlyphBuffer> CreateGlyphBuffer(
      const std::string& utf8_string,
      const scoped_refptr<render_tree::Font>& font) {
    return scoped_refptr<render_tree::GlyphBuffer>(
        CreateGlyphBufferMock(utf8_string, font.get()));
  }
  scoped_refptr<LottieAnimation> CreateLottieAnimation(const char* data,
                                                       size_t length) {
    return scoped_refptr<LottieAnimation>(
        CreateLottieAnimationMock(data, length));
  }

  virtual scoped_refptr<Mesh> CreateMesh(
      std::unique_ptr<std::vector<Mesh::Vertex> > vertices,
      Mesh::DrawMode draw_mode) {
    return base::WrapRefCounted(CreateMeshMock(vertices.get(), draw_mode));
  }
};

}  // namespace render_tree
}  // namespace cobalt

#endif  // COBALT_RENDER_TREE_MOCK_RESOURCE_PROVIDER_H_
