// -*- c++ -*-
//          Copyright Johannes Kapfhammer 2019-2022.
// Distributed under the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE_1_0.txt or copy at
//          http://www.boost.org/LICENSE_1_0.txt)

#ifndef SOI_HEADER_INCLUDED
#define SOI_HEADER_INCLUDED

#include "bits/include-all.hpp"

#include "bits/soi-dbg.hpp"
#include <fstream>

namespace soi {

void check_for_eof() {
  if (!(std::cin >> std::ws).eof())
    std::cerr << "WARNING: didn't read the whole input\n";
}

void noninteractive_check_eof() {
  // make symbol 0x1A (Ctrl+Z) a whitespace
  struct console_ctype : std::ctype<char> {
    static const mask *get_table() {
      static const std::array<mask, table_size> table = []() {
        std::array<mask, table_size> table;
        std::copy(classic_table(), classic_table() + table_size, table.begin());
        table['\x1a'] |= space;
        return table;
      }();
      return table.data();
    }
    console_ctype(std::size_t refs = 0) : ctype(get_table(), false, refs) {}
  };
  std::cin.imbue(std::locale(std::cin.getloc(), new console_ctype));
  check_for_eof();
}

bool should_check_for_eof() {
  if (const char *eofcheck_enabled = std::getenv("SOI_EOFCHECK")) {
    if (!std::strcmp(eofcheck_enabled, "1"))
      return true;
    if (!std::strcmp(eofcheck_enabled, "0"))
      return false;
  }
  return false;
}

void initialize_debug() {
  std::cout << std::unitbuf; // enable automatic flushing
  std::cin.exceptions(std::ifstream::failbit | std::ifstream::badbit);
  std::ios::sync_with_stdio(false);

  if (should_check_for_eof() && std::atexit(noninteractive_check_eof) != 0) {
    std::cerr
        << "WARNING: soi.h -- registration of sanity check at exit failed\n";
  }
  soi::detail::dbg_init();
}

struct soi_initializer {
  soi_initializer(bool release) {
    if (release) {
      std::ios::sync_with_stdio(false);
      std::cin.tie(0);
    } else {
      initialize_debug();
    }
  }
};

#ifdef SOI_RELEASE
soi_initializer soi_initializer_{true};
#else
soi_initializer soi_initializer_{false};
#endif

void interactive_task() {
  std::cin.tie(&std::cout);
}

} // end namespace soi

#include "bits/soi-io.hpp"
#include "bits/soi-redirect.hpp"
#include "bits/soi-deprecate.hpp"

using soi::interactive_task;

#define int int64_t
using namespace std;

#endif // SOI_HEADER_INCLUDED