// Copyright 2018 The Bazel Authors. All rights reserved.
//
// 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.

#ifndef BAZEL_TOOLS_TEST_WINDOWS_TW_H_
#define BAZEL_TOOLS_TEST_WINDOWS_TW_H_

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#include <memory>
#include <string>
#include <vector>

namespace bazel {

namespace windows {
class AutoHandle;
}  // namespace windows

namespace tools {
namespace test_wrapper {

// Info about a file/directory in the results of TestOnly_GetFileListRelativeTo.
class FileInfo {
 public:
  // C'tor for a directory.
  FileInfo(const std::wstring& rel_path)
      : rel_path_(rel_path), size_(0), is_dir_(true) {}

  // C'tor for a file.
  // Marked "explicit" because `size` is just a `int`.
  explicit FileInfo(const std::wstring& rel_path, int size)
      : rel_path_(rel_path), size_(size), is_dir_(false) {}

  inline const std::wstring& RelativePath() const { return rel_path_; }

  inline int Size() const { return size_; }

  inline bool IsDirectory() const { return is_dir_; }

 private:
  // The file's path, relative to the traversal root.
  std::wstring rel_path_;

  // The file's size, in bytes.
  //
  // Unfortunately this field has to be `int`, so it can only describe files up
  // to 2 GiB in size. The reason is, devtools_ijar::Stat::total_size is
  // declared as `int`, which is what we ultimately store the file size in,
  // therefore this field is also `int`.
  int size_;

  // Whether this is a directory (true) or a regular file (false).
  bool is_dir_;
};

// Zip entry paths for devtools_ijar::ZipBuilder.
// The function signatures mirror the signatures of ZipBuilder's functions.
class ZipEntryPaths {
 public:
  // Initialize the strings in this object.
  // `root` must be an absolute mixed-style path (Windows path with "/"
  // separators).
  // `files` must be relative, Unix-style paths.
  void Create(const std::string& root, const std::vector<std::string>& files);

  // Returns the number of paths in `AbsPathPtrs` and `EntryPathPtrs`.
  size_t Size() const { return size_; }

  // Returns a mutable array of const pointers to const char data.
  // Each pointer points to an absolute path: the file to archive.
  // The pointers are owned by this object and become invalid when the object is
  // destroyed.
  // Each entry corresponds to the entry at the same index in `EntryPathPtrs`.
  char const* const* AbsPathPtrs() const { return abs_path_ptrs_.get(); }

  // Returns a mutable array of const pointers to const char data.
  // Each pointer points to a relative path: an entry in the zip file.
  // The pointers are owned by this object and become invalid when the object is
  // destroyed.
  // Each entry corresponds to the entry at the same index in `AbsPathPtrs`.
  char const* const* EntryPathPtrs() const { return entry_path_ptrs_.get(); }

 private:
  size_t size_;
  std::unique_ptr<char[]> abs_paths_;
  std::unique_ptr<char*[]> abs_path_ptrs_;
  std::unique_ptr<char*[]> entry_path_ptrs_;
};

// Streams data from an input to two outputs.
// Inspired by tee(1) in the GNU coreutils.
class Tee {
 public:
  virtual ~Tee() {}

 protected:
  Tee() {}
  Tee(const Tee&) = delete;
  Tee& operator=(const Tee&) = delete;
};

// Buffered input stream (based on a HANDLE) with peek-ahead support.
class IFStream {
 public:
  virtual ~IFStream() {}

  // Gets the current byte under the read cursor.
  // Returns true upon success, returns false if there's no more data to read.
  virtual bool Get(uint8_t* result) const = 0;

  // Advances the read cursor one byte ahead. May fetch data from the underlying
  // HANDLE.
  // Returns true if the cursor could be moved. Returns false if EOF was reached
  // or if there was an I/O error.
  virtual bool Advance() = 0;

  // Peeks at the next byte after the read cursor. Returns true if there's at
  // least one more byte in the stream.
  bool Peek1(uint8_t* result) const { return PeekN(1, result); }

  // Peeks at the next two bytes after the read cursor. Returns true if there
  // are at least two more byte in the stream.
  bool Peek2(uint8_t* result) const { return PeekN(2, result); }

  // Peeks at the next three bytes after the read cursor. Returns true if there
  // are at least three more byte in the stream.
  bool Peek3(uint8_t* result) const { return PeekN(3, result); }

 protected:
  IFStream() {}
  IFStream(const IFStream&) = delete;
  IFStream& operator=(const IFStream&) = delete;

  // Peeks ahead N bytes, writing them to 'result'. Returns true if successful.
  // The result does not include the byte currently under the read cursor.
  virtual bool PeekN(DWORD n, uint8_t* result) const = 0;
};

// The main function of the test wrapper.
int TestWrapperMain(int argc, wchar_t** argv);

// The main function of the test XML writer.
int XmlWriterMain(int argc, wchar_t** argv);

// The "testing" namespace contains functions that should only be used by tests.
namespace testing {

// Retrieves an environment variable.
bool TestOnly_GetEnv(const wchar_t* name, std::wstring* result);

// Lists all files under `abs_root`, with paths relative to `abs_root`.
// Limits the directory depth to `depth_limit` many directories below
// `abs_root`.
// A negative depth means unlimited depth. 0 depth means searching only
// `abs_root`, while a positive depth limit allows matches in up to that many
// subdirectories.
bool TestOnly_GetFileListRelativeTo(const std::wstring& abs_root,
                                    std::vector<FileInfo>* result,
                                    int depth_limit = -1);

// Converts a list of files to ZIP file entry paths.a
bool TestOnly_ToZipEntryPaths(
    const std::wstring& abs_root,
    const std::vector<bazel::tools::test_wrapper::FileInfo>& files,
    ZipEntryPaths* result);

// Archives `files` into a zip file at `abs_zip` (absolute path to the zip).
bool TestOnly_CreateZip(const std::wstring& abs_root,
                        const std::vector<FileInfo>& files,
                        const std::wstring& abs_zip);

// Returns the MIME type of a file. The file does not need to exist.
std::string TestOnly_GetMimeType(const std::string& filename);

// Returns the contents of the Undeclared Outputs manifest.
bool TestOnly_CreateUndeclaredOutputsManifest(
    const std::vector<FileInfo>& files, std::string* result);

bool TestOnly_CreateUndeclaredOutputsAnnotations(
    const std::wstring& abs_root, const std::wstring& abs_output);

bool TestOnly_AsMixedPath(const std::wstring& path, std::string* result);

// Creates a Tee object. See the Tee class declaration for more info.
bool TestOnly_CreateTee(bazel::windows::AutoHandle* input,
                        bazel::windows::AutoHandle* output1,
                        bazel::windows::AutoHandle* output2,
                        std::unique_ptr<Tee>* result);

bool TestOnly_CdataEncodeBuffer(uint8_t* buffer, const DWORD size,
                                std::vector<DWORD>* cdata_end_locations);

bool TestOnly_CdataEscapeAndAppend(const std::wstring& abs_input,
                                   const std::wstring& abs_output);

IFStream* TestOnly_CreateIFStream(bazel::windows::AutoHandle* handle,
                                  DWORD page_size);

}  // namespace testing

}  // namespace test_wrapper
}  // namespace tools
}  // namespace bazel

#endif  // BAZEL_TOOLS_TEST_WINDOWS_TW_H_
