// 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/immutable_buffer.h"

#include <cstring>

#include "flutter/fml/file.h"
#include "flutter/fml/make_copyable.h"
#include "flutter/lib/ui/ui_dart_state.h"
#include "flutter/lib/ui/window/platform_configuration.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_persistent_value.h"

#if FML_OS_ANDROID
#include <sys/mman.h>
#endif

namespace flutter {

IMPLEMENT_WRAPPERTYPEINFO(ui, ImmutableBuffer);

ImmutableBuffer::~ImmutableBuffer() {}

Dart_Handle ImmutableBuffer::init(Dart_Handle buffer_handle,
                                  Dart_Handle data,
                                  Dart_Handle callback_handle) {
  if (!Dart_IsClosure(callback_handle)) {
    return tonic::ToDart("Callback must be a function");
  }

  tonic::Uint8List dataList = tonic::Uint8List(data);

  auto sk_data = MakeSkDataWithCopy(dataList.data(), dataList.num_elements());
  dataList.Release();
  auto buffer = fml::MakeRefCounted<ImmutableBuffer>(sk_data);
  buffer->AssociateWithDartWrapper(buffer_handle);
  tonic::DartInvoke(callback_handle, {Dart_TypeVoid()});

  return Dart_Null();
}

Dart_Handle ImmutableBuffer::initFromAsset(Dart_Handle buffer_handle,
                                           Dart_Handle asset_name_handle,
                                           Dart_Handle callback_handle) {
  UIDartState::ThrowIfUIOperationsProhibited();
  if (!Dart_IsClosure(callback_handle)) {
    return tonic::ToDart("Callback must be a function");
  }

  uint8_t* chars = nullptr;
  intptr_t asset_length = 0;
  Dart_Handle result =
      Dart_StringToUTF8(asset_name_handle, &chars, &asset_length);
  if (Dart_IsError(result)) {
    return tonic::ToDart("Asset name must be valid UTF8");
  }

  std::string asset_name = std::string{reinterpret_cast<const char*>(chars),
                                       static_cast<size_t>(asset_length)};

  std::shared_ptr<AssetManager> asset_manager = UIDartState::Current()
                                                    ->platform_configuration()
                                                    ->client()
                                                    ->GetAssetManager();
  std::unique_ptr<fml::Mapping> data = asset_manager->GetAsMapping(asset_name);
  if (data == nullptr) {
    return tonic::ToDart("Asset not found");
  }

  auto size = data->GetSize();
  const void* bytes = static_cast<const void*>(data->GetMapping());
  auto sk_data = MakeSkDataWithCopy(bytes, size);
  auto buffer = fml::MakeRefCounted<ImmutableBuffer>(sk_data);
  buffer->AssociateWithDartWrapper(buffer_handle);
  tonic::DartInvoke(callback_handle, {tonic::ToDart(size)});
  return Dart_Null();
}

Dart_Handle ImmutableBuffer::initFromFile(Dart_Handle raw_buffer_handle,
                                          Dart_Handle file_path_handle,
                                          Dart_Handle callback_handle) {
  UIDartState::ThrowIfUIOperationsProhibited();
  if (!Dart_IsClosure(callback_handle)) {
    return tonic::ToDart("Callback must be a function");
  }

  uint8_t* chars = nullptr;
  intptr_t file_path_length = 0;
  Dart_Handle result =
      Dart_StringToUTF8(file_path_handle, &chars, &file_path_length);
  if (Dart_IsError(result)) {
    return tonic::ToDart("File path must be valid UTF8");
  }

  std::string file_path = std::string{reinterpret_cast<const char*>(chars),
                                      static_cast<size_t>(file_path_length)};

  auto* dart_state = UIDartState::Current();
  auto ui_task_runner = dart_state->GetTaskRunners().GetUITaskRunner();
  auto buffer_callback =
      std::make_unique<tonic::DartPersistentValue>(dart_state, callback_handle);
  auto buffer_handle = std::make_unique<tonic::DartPersistentValue>(
      dart_state, raw_buffer_handle);

  auto ui_task = fml::MakeCopyable(
      [buffer_callback = std::move(buffer_callback),
       buffer_handle = std::move(buffer_handle)](const sk_sp<SkData>& sk_data,
                                                 size_t buffer_size) mutable {
        auto dart_state = buffer_callback->dart_state().lock();
        if (!dart_state) {
          return;
        }
        tonic::DartState::Scope scope(dart_state);
        if (!sk_data) {
          // -1 is used as a sentinel that the file could not be opened.
          tonic::DartInvoke(buffer_callback->Get(), {tonic::ToDart(-1)});
          return;
        }
        auto buffer = fml::MakeRefCounted<ImmutableBuffer>(sk_data);
        buffer->AssociateWithDartWrapper(buffer_handle->Get());
        tonic::DartInvoke(buffer_callback->Get(), {tonic::ToDart(buffer_size)});
      });

  dart_state->GetConcurrentTaskRunner()->PostTask(
      [file_path = std::move(file_path),
       ui_task_runner = std::move(ui_task_runner), ui_task] {
        auto mapping = std::make_unique<fml::FileMapping>(fml::OpenFile(
            file_path.c_str(), false, fml::FilePermission::kRead));

        sk_sp<SkData> sk_data;
        size_t buffer_size = 0;
        if (mapping->IsValid()) {
          buffer_size = mapping->GetSize();
          const void* bytes = static_cast<const void*>(mapping->GetMapping());
          sk_data = MakeSkDataWithCopy(bytes, buffer_size);
        }
        ui_task_runner->PostTask(
            [sk_data = std::move(sk_data), ui_task = std::move(ui_task),
             buffer_size]() { ui_task(sk_data, buffer_size); });
      });
  return Dart_Null();
}

#if FML_OS_ANDROID

// Compressed image buffers are allocated on the UI thread but are deleted on a
// decoder worker thread.  Android's implementation of malloc appears to
// continue growing the native heap size when the allocating thread is
// different from the freeing thread.  To work around this, create an SkData
// backed by an anonymous mapping.
sk_sp<SkData> ImmutableBuffer::MakeSkDataWithCopy(const void* data,
                                                  size_t length) {
  if (length == 0) {
    return SkData::MakeEmpty();
  }

  size_t mapping_length = length + sizeof(size_t);
  void* mapping = ::mmap(nullptr, mapping_length, PROT_READ | PROT_WRITE,
                         MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);

  if (mapping == MAP_FAILED) {
    return SkData::MakeEmpty();
  }

  *reinterpret_cast<size_t*>(mapping) = mapping_length;
  void* mapping_data = reinterpret_cast<char*>(mapping) + sizeof(size_t);
  ::memcpy(mapping_data, data, length);

  SkData::ReleaseProc proc = [](const void* ptr, void* context) {
    size_t* size_ptr = reinterpret_cast<size_t*>(context);
    FML_DCHECK(ptr == size_ptr + 1);
    if (::munmap(const_cast<void*>(context), *size_ptr) == -1) {
      FML_LOG(ERROR) << "munmap of codec SkData failed";
    }
  };

  return SkData::MakeWithProc(mapping_data, length, proc, mapping);
}

#else

sk_sp<SkData> ImmutableBuffer::MakeSkDataWithCopy(const void* data,
                                                  size_t length) {
  return SkData::MakeWithCopy(data, length);
}

#endif  // FML_OS_ANDROID

}  // namespace flutter
