// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "dap/io.h"

#include <atomic>
#include <condition_variable>
#include <cstdarg>
#include <cstdio>
#include <cstring>  // strlen
#include <deque>
#include <mutex>

namespace {

class Pipe : public dap::ReaderWriter {
 public:
  // dap::ReaderWriter compliance
  bool isOpen() override {
    std::unique_lock<std::mutex> lock(mutex);
    return !closed;
  }

  void close() override {
    std::unique_lock<std::mutex> lock(mutex);
    closed = true;
    cv.notify_all();
  }

  size_t read(void* buffer, size_t bytes) override {
    std::unique_lock<std::mutex> lock(mutex);
    auto out = reinterpret_cast<uint8_t*>(buffer);
    size_t n = 0;
    while (true) {
      cv.wait(lock, [&] { return closed || data.size() > 0; });
      if (closed) {
        return n;
      }
      for (; n < bytes && data.size() > 0; n++) {
        out[n] = data.front();
        data.pop_front();
      }
      if (n == bytes) {
        return n;
      }
    }
  }

  bool write(const void* buffer, size_t bytes) override {
    std::unique_lock<std::mutex> lock(mutex);
    if (closed) {
      return false;
    }
    if (bytes == 0) {
      return true;
    }
    auto notify = data.size() == 0;
    auto src = reinterpret_cast<const uint8_t*>(buffer);
    for (size_t i = 0; i < bytes; i++) {
      data.emplace_back(src[i]);
    }
    if (notify) {
      cv.notify_all();
    }
    return true;
  }

 private:
  std::mutex mutex;
  std::condition_variable cv;
  std::deque<uint8_t> data;
  bool closed = false;
};

class RW : public dap::ReaderWriter {
 public:
  RW(const std::shared_ptr<Reader>& r, const std::shared_ptr<Writer>& w)
      : r(r), w(w) {}

  // dap::ReaderWriter compliance
  bool isOpen() override { return r->isOpen() && w->isOpen(); }
  void close() override {
    r->close();
    w->close();
  }
  size_t read(void* buffer, size_t n) override { return r->read(buffer, n); }
  bool write(const void* buffer, size_t n) override {
    return w->write(buffer, n);
  }

 private:
  const std::shared_ptr<dap::Reader> r;
  const std::shared_ptr<dap::Writer> w;
};

class File : public dap::ReaderWriter {
 public:
  File(FILE* f, bool closable) : f(f), closable(closable) {}

  ~File() { close(); }

  // dap::ReaderWriter compliance
  bool isOpen() override { return !closed; }
  void close() override {
    if (closable) {
      if (!closed.exchange(true)) {
        fclose(f);
      }
    }
  }
  size_t read(void* buffer, size_t n) override {
    std::unique_lock<std::mutex> lock(readMutex);
    auto out = reinterpret_cast<char*>(buffer);
    for (size_t i = 0; i < n; i++) {
      int c = fgetc(f);
      if (c == EOF) {
        return i;
      }
      out[i] = char(c);
    }
    return n;
    // return fread(buffer, 1, n, f);
  }
  bool write(const void* buffer, size_t n) override {
    std::unique_lock<std::mutex> lock(writeMutex);
    if (fwrite(buffer, 1, n, f) == n) {
      fflush(f);
      return true;
    }
    return false;
  }

 private:
  FILE* const f;
  std::mutex readMutex;
  std::mutex writeMutex;
  std::atomic<bool> closed;
  const bool closable;
};

class ReaderSpy : public dap::Reader {
 public:
  ReaderSpy(const std::shared_ptr<dap::Reader>& r,
            const std::shared_ptr<dap::Writer>& s,
            const std::string& prefix)
      : r(r), s(s), prefix(prefix) {}

  // dap::Reader compliance
  bool isOpen() override { return r->isOpen(); }
  void close() override { r->close(); }
  size_t read(void* buffer, size_t n) override {
    auto c = r->read(buffer, n);
    if (c > 0) {
      auto chars = reinterpret_cast<const char*>(buffer);
      std::string buf = prefix;
      buf.append(chars, chars + c);
      s->write(buf.data(), buf.size());
    }
    return c;
  }

 private:
  const std::shared_ptr<dap::Reader> r;
  const std::shared_ptr<dap::Writer> s;
  const std::string prefix;
};

class WriterSpy : public dap::Writer {
 public:
  WriterSpy(const std::shared_ptr<dap::Writer>& w,
            const std::shared_ptr<dap::Writer>& s,
            const std::string& prefix)
      : w(w), s(s), prefix(prefix) {}

  // dap::Writer compliance
  bool isOpen() override { return w->isOpen(); }
  void close() override { w->close(); }
  bool write(const void* buffer, size_t n) override {
    if (!w->write(buffer, n)) {
      return false;
    }
    auto chars = reinterpret_cast<const char*>(buffer);
    std::string buf = prefix;
    buf.append(chars, chars + n);
    s->write(buf.data(), buf.size());
    return true;
  }

 private:
  const std::shared_ptr<dap::Writer> w;
  const std::shared_ptr<dap::Writer> s;
  const std::string prefix;
};

}  // anonymous namespace

namespace dap {

std::shared_ptr<ReaderWriter> ReaderWriter::create(
    const std::shared_ptr<Reader>& r,
    const std::shared_ptr<Writer>& w) {
  return std::make_shared<RW>(r, w);
}

std::shared_ptr<ReaderWriter> pipe() {
  return std::make_shared<Pipe>();
}

std::shared_ptr<ReaderWriter> file(FILE* f, bool closable /* = true */) {
  return std::make_shared<File>(f, closable);
}

std::shared_ptr<ReaderWriter> file(const char* path) {
  if (auto f = fopen(path, "wb")) {
    return std::make_shared<File>(f, true);
  }
  return nullptr;
}

// spy() returns a Reader that copies all reads from the Reader r to the Writer
// s, using the given optional prefix.
std::shared_ptr<Reader> spy(const std::shared_ptr<Reader>& r,
                            const std::shared_ptr<Writer>& s,
                            const char* prefix /* = "\n<-" */) {
  return std::make_shared<ReaderSpy>(r, s, prefix);
}

// spy() returns a Writer that copies all writes to the Writer w to the Writer
// s, using the given optional prefix.
std::shared_ptr<Writer> spy(const std::shared_ptr<Writer>& w,
                            const std::shared_ptr<Writer>& s,
                            const char* prefix /* = "\n->" */) {
  return std::make_shared<WriterSpy>(w, s, prefix);
}

bool writef(const std::shared_ptr<Writer>& w, const char* msg, ...) {
  char buf[2048];

  va_list vararg;
  va_start(vararg, msg);
  vsnprintf(buf, sizeof(buf), msg, vararg);
  va_end(vararg);

  return w->write(buf, strlen(buf));
}

}  // namespace dap