// 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 "flutter/lib/ui/painting/path_measure.h"

#include <cmath>

#include "flutter/lib/ui/floating_point.h"
#include "flutter/lib/ui/painting/matrix.h"
#include "flutter/lib/ui/ui_dart_state.h"
#include "third_party/tonic/converter/dart_converter.h"
#include "third_party/tonic/dart_args.h"
#include "third_party/tonic/dart_binding_macros.h"
#include "third_party/tonic/dart_library_natives.h"

namespace flutter {

typedef CanvasPathMeasure PathMeasure;

IMPLEMENT_WRAPPERTYPEINFO(ui, PathMeasure);

void CanvasPathMeasure::Create(Dart_Handle wrapper,
                               const CanvasPath* path,
                               bool forceClosed) {
  UIDartState::ThrowIfUIOperationsProhibited();
  fml::RefPtr<CanvasPathMeasure> pathMeasure =
      fml::MakeRefCounted<CanvasPathMeasure>();
  if (path) {
    const SkPath& skPath = path->path();
    SkScalar resScale = 1;
    pathMeasure->path_measure_ =
        std::make_unique<SkContourMeasureIter>(skPath, forceClosed, resScale);
  } else {
    pathMeasure->path_measure_ = std::make_unique<SkContourMeasureIter>();
  }
  pathMeasure->AssociateWithDartWrapper(wrapper);
}

CanvasPathMeasure::CanvasPathMeasure() {}

CanvasPathMeasure::~CanvasPathMeasure() {}

void CanvasPathMeasure::setPath(const CanvasPath* path, bool isClosed) {
  const SkPath& skPath = path->path();
  path_measure_->reset(skPath, isClosed);
}

double CanvasPathMeasure::getLength(int contour_index) {
  if (static_cast<std::vector<sk_sp<SkContourMeasure>>::size_type>(
          contour_index) < measures_.size()) {
    return measures_[contour_index]->length();
  }
  return -1;
}

tonic::Float32List CanvasPathMeasure::getPosTan(int contour_index,
                                                double distance) {
  tonic::Float32List posTan(Dart_NewTypedData(Dart_TypedData_kFloat32, 5));
  posTan[0] = 0;  // dart code will check for this for failure
  if (static_cast<std::vector<sk_sp<SkContourMeasure>>::size_type>(
          contour_index) >= measures_.size()) {
    return posTan;
  }

  SkPoint pos;
  SkVector tan;
  float fdistance = SafeNarrow(distance);
  bool success = measures_[contour_index]->getPosTan(fdistance, &pos, &tan);

  if (success) {
    posTan[0] = 1;  // dart code will check for this for success
    posTan[1] = pos.x();
    posTan[2] = pos.y();
    posTan[3] = tan.x();
    posTan[4] = tan.y();
  }

  return posTan;
}

void CanvasPathMeasure::getSegment(Dart_Handle path_handle,
                                   int contour_index,
                                   double start_d,
                                   double stop_d,
                                   bool start_with_move_to) {
  if (static_cast<std::vector<sk_sp<SkContourMeasure>>::size_type>(
          contour_index) >= measures_.size()) {
    CanvasPath::Create(path_handle);
  }
  SkPath dst;
  bool success = measures_[contour_index]->getSegment(
      SafeNarrow(start_d), SafeNarrow(stop_d), &dst, start_with_move_to);
  if (!success) {
    CanvasPath::Create(path_handle);
  } else {
    CanvasPath::CreateFrom(path_handle, dst);
  }
}

bool CanvasPathMeasure::isClosed(int contour_index) {
  if (static_cast<std::vector<sk_sp<SkContourMeasure>>::size_type>(
          contour_index) < measures_.size()) {
    return measures_[contour_index]->isClosed();
  }
  return false;
}

bool CanvasPathMeasure::nextContour() {
  auto measure = path_measure_->next();
  if (measure) {
    measures_.push_back(std::move(measure));
    return true;
  }
  return false;
}

}  // namespace flutter
