/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * 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
 *
 *      http://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 <sstream>
#include <string>
#include <thread>
#include <vector>

#include "common/libs/fs/shared_buf.h"
#include "common/libs/fs/shared_fd.h"

namespace cuttlefish {

namespace {

const size_t BUFF_SIZE = 1 << 14;

} // namespace

ssize_t WriteAll(SharedFD fd, const char* buf, size_t size) {
  size_t total_written = 0;
  ssize_t written = 0;
  while ((written = fd->Write((void*)&(buf[total_written]), size - total_written)) > 0) {
    if (written < 0) {
      errno = fd->GetErrno();
      return written;
    }
    total_written += written;
    if (total_written == size) {
      break;
    }
  }
  return total_written;
}

ssize_t ReadExact(SharedFD fd, char* buf, size_t size) {
  size_t total_read = 0;
  ssize_t read = 0;
  while ((read = fd->Read((void*)&(buf[total_read]), size - total_read)) > 0) {
    if (read < 0) {
      errno = fd->GetErrno();
      return read;
    }
    total_read += read;
    if (total_read == size) {
      break;
    }
  }
  return total_read;
}

ssize_t ReadAll(SharedFD fd, std::string* buf) {
  char buff[BUFF_SIZE];
  std::stringstream ss;
  ssize_t read;
  while ((read = fd->Read(buff, BUFF_SIZE - 1)) > 0) {
    // this is necessary to avoid problems with having a '\0' in the middle of the buffer
    ss << std::string(buff, read);
  }
  if (read < 0) {
    errno = fd->GetErrno();
    return read;
  }
  *buf = ss.str();
  return buf->size();
}

ssize_t ReadExact(SharedFD fd, std::string* buf) {
  return ReadExact(fd, buf->data(), buf->size());
}

ssize_t ReadExact(SharedFD fd, std::vector<char>* buf) {
  return ReadExact(fd, buf->data(), buf->size());
}

ssize_t WriteAll(SharedFD fd, const std::string& buf) {
  return WriteAll(fd, buf.data(), buf.size());
}

ssize_t WriteAll(SharedFD fd, const std::vector<char>& buf) {
  return WriteAll(fd, buf.data(), buf.size());
}

bool SendAll(SharedFD sock, const std::string& msg) {
  ssize_t total_written{};
  if (!sock->IsOpen()) {
    return false;
  }
  while (total_written < static_cast<ssize_t>(msg.size())) {
    auto just_written = sock->Send(msg.c_str() + total_written,
                                   msg.size() - total_written, MSG_NOSIGNAL);
    if (just_written <= 0) {
      return false;
    }
    total_written += just_written;
  }
  return true;
}

std::string RecvAll(SharedFD sock, const size_t count) {
  size_t total_read{};
  if (!sock->IsOpen()) {
    return {};
  }
  std::unique_ptr<char[]> data(new char[count]);
  while (total_read < count) {
    auto just_read = sock->Read(data.get() + total_read, count - total_read);
    if (just_read <= 0) {
      return {};
    }
    total_read += just_read;
  }
  return {data.get(), count};
}

} // namespace cuttlefish
