#include "HCAAsyncWorker.h"

void BufferFinalizer(Napi::Env env, void* data, void* hint);

HCAAsyncWorker::HCAAsyncWorker(unsigned int ciphKey1, unsigned int ciphKey2, const std::string& hcaFile, const std::string& wav, double volumn, int mode, int loop, const Napi::Function& callback)
  : Napi::AsyncWorker(callback),
    _hca(ciphKey1, ciphKey2),
    _hcaFile(hcaFile),
    _hcabuf(nullptr),
    _hcasize(0),
    _hcaArrayBuffer(),
    _wavFile(wav),
    _volumn(volumn),
    _mode(mode),
    _loop(loop),
    _res(false),
    _buf(nullptr) {}

HCAAsyncWorker::HCAAsyncWorker(unsigned int ciphKey1, unsigned int ciphKey2, const Napi::Object& hca, const std::string& wav, double volumn, int mode, int loop, const Napi::Function& callback)
  : Napi::AsyncWorker(callback),
    _hca(ciphKey1, ciphKey2),
    _hcaFile(""),
    _hcabuf(hca.As<Napi::ArrayBuffer>().Data()),
    _hcasize(hca.As<Napi::ArrayBuffer>().ByteLength()),
    _hcaArrayBuffer(Napi::Persistent(hca)),
    _wavFile(wav),
    _volumn(volumn),
    _mode(mode),
    _loop(loop),
    _res(false),
    _buf(nullptr) {}

void HCAAsyncWorker::Execute() {
  if (_wavFile != "") {
    if (_hcaFile != "") {
      _res = _hca.DecodeToWavefile(_hcaFile.c_str(), _wavFile.c_str(), _volumn, _mode, _loop);
    } else {
      HCAFileStream stream = HCAFileStream::Open(_hcabuf, _hcasize);
      _res = _hca.DecodeToWavefile(stream, _wavFile.c_str(), _volumn, _mode, _loop);
    }
  } else {
    HCAFileStream stream = HCAFileStream::Open();
    if (_hcaFile != "") {
      _res = _hca.DecodeToMemory(_hcaFile.c_str(), stream, _volumn, _mode, _loop);
    } else {
      HCAFileStream hcaReadStream = HCAFileStream::Open(_hcabuf, _hcasize);
      _res = _hca.DecodeToMemory(hcaReadStream, stream, _volumn, _mode, _loop);
    }
    if (_res) {
      _buf = stream.Release();
    }
  }
}

void HCAAsyncWorker::OnOK() {
  Napi::Env env = Env();
  if (_res) {
    if (!Callback().IsEmpty()) {
      if (_wavFile != "") {
        Callback().Call({ env.Null(), Napi::String::New(env, _wavFile) });
      } else {
        if (_buf) {
          Callback().Call({ env.Null(), Napi::Buffer<uint8_t>::NewOrCopy(env, _buf->data(), _buf->size(), BufferFinalizer, _buf) });
        } else {
          Callback().Call({ Napi::Error::New(env, _hcaFile + " decode failed.").Value(), env.Null() });
        }
      }
    }
  } else {
    if (!Callback().IsEmpty()) {
      Callback().Call({ Napi::Error::New(env, _hcaFile + " decode failed.").Value(), Napi::String::New(env, "") });
    }
  }
}
