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

#include <vector>

#include "impeller/display_list/nine_patch_converter.h"

namespace impeller {

NinePatchConverter::NinePatchConverter() = default;

NinePatchConverter::~NinePatchConverter() = default;

std::vector<double> NinePatchConverter::InitSlices(double img0,
                                                   double imgC0,
                                                   double imgC1,
                                                   double img1,
                                                   double dst0,
                                                   double dst1) {
  auto imageDim = img1 - img0;
  auto destDim = dst1 - dst0;

  if (imageDim == destDim) {
    // If the src and dest are the same size then we do not need scaling
    // We return 4 values for a single slice
    return {img0, dst0, img1, dst1};
  }

  auto edge0Dim = imgC0 - img0;
  auto edge1Dim = img1 - imgC1;
  auto edgesDim = edge0Dim + edge1Dim;

  if (edgesDim >= destDim) {
    // the center portion has disappeared, leaving only the edges to scale to a
    // common center position in the destination this produces only 2 slices
    // which is 8 values
    auto dstC = dst0 + destDim * edge0Dim / edgesDim;
    // clang-format off
    return {
      img0,  dst0, imgC0, dstC,
      imgC1, dstC, img1,  dst1,
    };
    // clang-format on
  }

  // center portion is nonEmpty and only that part is scaled
  // we need 3 slices which is 12 values
  auto dstC0 = dst0 + edge0Dim;
  auto dstC1 = dst1 - edge1Dim;
  // clang-format off
  return {
    img0,  dst0,  imgC0, dstC0,
    imgC0, dstC0, imgC1, dstC1,
    imgC1, dstC1, img1,  dst1,
  };
  // clang-format on
}

void NinePatchConverter::DrawNinePatch(const std::shared_ptr<Image>& image,
                                       Rect center,
                                       Rect dst,
                                       const SamplerDescriptor& sampler,
                                       Canvas* canvas,
                                       Paint* paint) {
  if (dst.IsEmpty()) {
    return;
  }
  auto image_size = image->GetSize();
  auto hSlices = InitSlices(0, center.GetLeft(), center.GetRight(),
                            image_size.width, dst.GetLeft(), dst.GetRight());
  auto vSlices = InitSlices(0, center.GetTop(), center.GetBottom(),
                            image_size.height, dst.GetTop(), dst.GetBottom());

  for (size_t yi = 0; yi < vSlices.size(); yi += 4) {
    auto srcY0 = vSlices[yi];
    auto dstY0 = vSlices[yi + 1];
    auto srcY1 = vSlices[yi + 2];
    auto dstY1 = vSlices[yi + 3];
    for (size_t xi = 0; xi < hSlices.size(); xi += 4) {
      auto srcX0 = hSlices[xi];
      auto dstX0 = hSlices[xi + 1];
      auto srcX1 = hSlices[xi + 2];
      auto dstX1 = hSlices[xi + 3];
      // TODO(jonahwilliams): consider converting this into a single call to
      // DrawImageAtlas.
      canvas->DrawImageRect(image, Rect::MakeLTRB(srcX0, srcY0, srcX1, srcY1),
                            Rect::MakeLTRB(dstX0, dstY0, dstX1, dstY1), *paint,
                            sampler);
    }
  }
}

}  // namespace impeller
