#pragma once

#include <cstddef>
#include <vector>

namespace qc {

struct Vec3 {
  double x{0.0};
  double y{0.0};
  double z{0.0};
};

Vec3 operator+(Vec3 a, Vec3 b);
Vec3 operator-(Vec3 a, Vec3 b);
Vec3 operator*(double s, Vec3 v);
double dot(Vec3 a, Vec3 b);
double norm(Vec3 v);
double dist_sq(Vec3 a, Vec3 b);

struct Atom {
  double Z{0.0};
  Vec3 r{};
};

struct CartPrimitive {
  double alpha{0.0};
  double coeff{0.0};
  Vec3 r{};
  int lx{0};
  int ly{0};
  int lz{0};
};

struct AOFunction {
  std::vector<CartPrimitive> prims;
};

struct Basis {
  std::vector<AOFunction> aos;

  std::size_t n_ao() const { return aos.size(); }
};

Basis sto3g_hydrogen_dimer(double bond_bohr);

double nuclear_repulsion_energy(const std::vector<Atom>& atoms);

}  // namespace qc
