// 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(std::shared_ptr<Image> image,
                                       Rect center,
                                       Rect dst,
                                       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
