/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#ifndef cmUVStreambuf_h
#define cmUVStreambuf_h

#include <algorithm>
#include <cstring>
#include <streambuf>
#include <vector>

#include <cm3p/uv.h>

#include "cmUVHandlePtr.h"

/*
 * This file is based on example code from:
 *
 * http://www.voidcn.com/article/p-vjnlygmc-gy.html
 *
 * The example code was distributed under the following license:
 *
 * Copyright 2007 Edd Dawson.
 * Distributed under the Boost Software License, Version 1.0.
 *
 * Boost Software License - Version 1.0 - August 17th, 2003
 *
 * Permission is hereby granted, free of charge, to any person or organization
 * obtaining a copy of the software and accompanying documentation covered by
 * this license (the "Software") to use, reproduce, display, distribute,
 * execute, and transmit the Software, and to prepare derivative works of the
 * Software, and to permit third-parties to whom the Software is furnished to
 * do so, all subject to the following:
 *
 * The copyright notices in the Software and this entire statement, including
 * the above license grant, this restriction and the following disclaimer,
 * must be included in all copies of the Software, in whole or in part, and
 * all derivative works of the Software, unless such copies or derivative
 * works are solely in the form of machine-executable object code generated by
 * a source language processor.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
 * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

template <typename CharT, typename Traits = std::char_traits<CharT>>
class cmBasicUVStreambuf : public std::basic_streambuf<CharT, Traits>
{
public:
  cmBasicUVStreambuf(std::size_t bufSize = 256, std::size_t putBack = 8);
  ~cmBasicUVStreambuf() override;

  bool is_open() const;

  cmBasicUVStreambuf* open(uv_stream_t* stream);

  cmBasicUVStreambuf* close();

protected:
  typename cmBasicUVStreambuf<CharT, Traits>::int_type underflow() override;
  std::streamsize showmanyc() override;

  // FIXME: Add write support

private:
  uv_stream_t* Stream = nullptr;
  void* OldStreamData = nullptr;
  const std::size_t PutBack = 0;
  std::vector<CharT> InputBuffer;
  bool EndOfFile = false;

  void StreamReadStartStop();

  void StreamRead(ssize_t nread);
  void HandleAlloc(uv_buf_t* buf);
};

template <typename CharT, typename Traits>
cmBasicUVStreambuf<CharT, Traits>::cmBasicUVStreambuf(std::size_t bufSize,
                                                      std::size_t putBack)
  : PutBack(std::max<std::size_t>(putBack, 1))
  , InputBuffer(std::max<std::size_t>(this->PutBack, bufSize) + this->PutBack)
{
  this->close();
}

template <typename CharT, typename Traits>
cmBasicUVStreambuf<CharT, Traits>::~cmBasicUVStreambuf()
{
  this->close();
}

template <typename CharT, typename Traits>
bool cmBasicUVStreambuf<CharT, Traits>::is_open() const
{
  return this->Stream != nullptr;
}

template <typename CharT, typename Traits>
cmBasicUVStreambuf<CharT, Traits>* cmBasicUVStreambuf<CharT, Traits>::open(
  uv_stream_t* stream)
{
  this->close();
  this->Stream = stream;
  this->EndOfFile = false;
  if (this->Stream) {
    this->OldStreamData = this->Stream->data;
    this->Stream->data = this;
  }
  this->StreamReadStartStop();
  return this;
}

template <typename CharT, typename Traits>
cmBasicUVStreambuf<CharT, Traits>* cmBasicUVStreambuf<CharT, Traits>::close()
{
  if (this->Stream) {
    uv_read_stop(this->Stream);
    this->Stream->data = this->OldStreamData;
  }
  this->Stream = nullptr;
  CharT* readEnd = this->InputBuffer.data() + this->InputBuffer.size();
  this->setg(readEnd, readEnd, readEnd);
  return this;
}

template <typename CharT, typename Traits>
typename cmBasicUVStreambuf<CharT, Traits>::int_type
cmBasicUVStreambuf<CharT, Traits>::underflow()
{
  if (!this->is_open()) {
    return Traits::eof();
  }

  if (this->gptr() < this->egptr()) {
    return Traits::to_int_type(*this->gptr());
  }

  this->StreamReadStartStop();
  while (this->in_avail() == 0) {
    uv_run(this->Stream->loop, UV_RUN_ONCE);
  }
  if (this->in_avail() == -1) {
    return Traits::eof();
  }
  return Traits::to_int_type(*this->gptr());
}

template <typename CharT, typename Traits>
std::streamsize cmBasicUVStreambuf<CharT, Traits>::showmanyc()
{
  if (!this->is_open() || this->EndOfFile) {
    return -1;
  }
  return 0;
}

template <typename CharT, typename Traits>
void cmBasicUVStreambuf<CharT, Traits>::StreamReadStartStop()
{
  if (this->Stream) {
    uv_read_stop(this->Stream);
    if (this->gptr() >= this->egptr()) {
      uv_read_start(
        this->Stream,
        [](uv_handle_t* handle, size_t /* unused */, uv_buf_t* buf) {
          auto streambuf =
            static_cast<cmBasicUVStreambuf<CharT, Traits>*>(handle->data);
          streambuf->HandleAlloc(buf);
        },
        [](uv_stream_t* stream2, ssize_t nread, const uv_buf_t* /* unused */) {
          auto streambuf =
            static_cast<cmBasicUVStreambuf<CharT, Traits>*>(stream2->data);
          streambuf->StreamRead(nread);
        });
    }
  }
}

template <typename CharT, typename Traits>
void cmBasicUVStreambuf<CharT, Traits>::HandleAlloc(uv_buf_t* buf)
{
  auto size = this->egptr() - this->gptr();
  std::memmove(this->InputBuffer.data(), this->gptr(),
               this->egptr() - this->gptr());
  this->setg(this->InputBuffer.data(), this->InputBuffer.data(),
             this->InputBuffer.data() + size);
  buf->base = this->egptr();
#ifdef _WIN32
#  define BUF_LEN_TYPE ULONG
#else
#  define BUF_LEN_TYPE size_t
#endif
  buf->len = BUF_LEN_TYPE(
    (this->InputBuffer.data() + this->InputBuffer.size() - this->egptr()) *
    sizeof(CharT));
#undef BUF_LEN_TYPE
}

template <typename CharT, typename Traits>
void cmBasicUVStreambuf<CharT, Traits>::StreamRead(ssize_t nread)
{
  if (nread > 0) {
    this->setg(this->eback(), this->gptr(),
               this->egptr() + nread / sizeof(CharT));
    uv_read_stop(this->Stream);
  } else if (nread < 0 /*|| nread == UV_EOF*/) {
    this->EndOfFile = true;
    uv_read_stop(this->Stream);
  }
}

using cmUVStreambuf = cmBasicUVStreambuf<char>;

#endif
