/*
 * Copyright (C) 2017 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 "io/Util.h"

#include "google/protobuf/io/zero_copy_stream_impl_lite.h"

#include "trace/TraceBuffer.h"

using ::android::StringPiece;
using ::google::protobuf::io::ZeroCopyOutputStream;

namespace aapt {
namespace io {

bool CopyInputStreamToArchive(IAaptContext* context, InputStream* in, const std::string& out_path,
                              uint32_t compression_flags, IArchiveWriter* writer) {
  TRACE_CALL();
  if (context->IsVerbose()) {
    context->GetDiagnostics()->Note(DiagMessage() << "writing " << out_path << " to archive");
  }

  if (!writer->WriteFile(out_path, compression_flags, in)) {
    context->GetDiagnostics()->Error(DiagMessage() << "failed to write " << out_path
                                                   << " to archive: " << writer->GetError());
    return false;
  }
  return true;
}

bool CopyFileToArchive(IAaptContext* context, io::IFile* file, const std::string& out_path,
                       uint32_t compression_flags, IArchiveWriter* writer) {
  TRACE_CALL();
  std::unique_ptr<io::IData> data = file->OpenAsData();
  if (!data) {
    context->GetDiagnostics()->Error(DiagMessage(file->GetSource()) << "failed to open file");
    return false;
  }
  return CopyInputStreamToArchive(context, data.get(), out_path, compression_flags, writer);
}

bool CopyFileToArchivePreserveCompression(IAaptContext* context, io::IFile* file,
                                          const std::string& out_path, IArchiveWriter* writer) {
  uint32_t compression_flags = file->WasCompressed() ? ArchiveEntry::kCompress : 0u;
  return CopyFileToArchive(context, file, out_path, compression_flags, writer);
}

bool CopyProtoToArchive(IAaptContext* context, ::google::protobuf::Message* proto_msg,
                        const std::string& out_path, uint32_t compression_flags,
                        IArchiveWriter* writer) {
  TRACE_CALL();
  if (context->IsVerbose()) {
    context->GetDiagnostics()->Note(DiagMessage() << "writing " << out_path << " to archive");
  }

  if (writer->StartEntry(out_path, compression_flags)) {
    // Make sure CopyingOutputStreamAdaptor is deleted before we call writer->FinishEntry().
    {
      // Wrap our IArchiveWriter with an adaptor that implements the ZeroCopyOutputStream interface.
      ::google::protobuf::io::CopyingOutputStreamAdaptor adaptor(writer);
      if (!proto_msg->SerializeToZeroCopyStream(&adaptor)) {
        context->GetDiagnostics()->Error(DiagMessage() << "failed to write " << out_path
                                                       << " to archive");
        return false;
      }
    }

    if (writer->FinishEntry()) {
      return true;
    }
  }
  context->GetDiagnostics()->Error(DiagMessage() << "failed to write " << out_path
                                                 << " to archive: " << writer->GetError());
  return false;
}

bool Copy(OutputStream* out, InputStream* in) {
  TRACE_CALL();
  const void* in_buffer;
  size_t in_len;
  while (in->Next(&in_buffer, &in_len)) {
    void* out_buffer;
    size_t out_len;
    if (!out->Next(&out_buffer, &out_len)) {
      return !out->HadError();
    }

    const size_t bytes_to_copy = in_len < out_len ? in_len : out_len;
    memcpy(out_buffer, in_buffer, bytes_to_copy);
    out->BackUp(out_len - bytes_to_copy);
    in->BackUp(in_len - bytes_to_copy);
  }
  return !in->HadError();
}

bool Copy(OutputStream* out, const StringPiece& in) {
  const char* in_buffer = in.data();
  size_t in_len = in.size();
  while (in_len != 0) {
    void* out_buffer;
    size_t out_len;
    if (!out->Next(&out_buffer, &out_len)) {
      return false;
    }

    const size_t bytes_to_copy = in_len < out_len ? in_len : out_len;
    memcpy(out_buffer, in_buffer, bytes_to_copy);
    out->BackUp(out_len - bytes_to_copy);
    in_buffer += bytes_to_copy;
    in_len -= bytes_to_copy;
  }
  return true;
}

bool Copy(ZeroCopyOutputStream* out, InputStream* in) {
  OutputStreamAdaptor adaptor(out);
  return Copy(&adaptor, in);
}

}  // namespace io
}  // namespace aapt
