#!/usr/bin/env perl
# Freezes gemmi's answer for the structures in this directory into oracle.txt.
#
# t/oracle.t compares every atom of model 1 against gemmi, which is a reader
# nobody here wrote.  gemmi is not something the distribution can require, so
# the comparison has to survive an installer who has never heard of it: this
# script writes down what gemmi said, and the test reads that instead of
# running python.  Where gemmi *is* installed the test does both and checks the
# two still agree, which is what keeps the frozen file honest.
#
# Run it from t/data/ after adding or changing a structure here, and commit
# both the script and what it wrote:
#
#     STRUCTURE_INFO_PYTHON=/home/con/.pyenv/versions/3.14.2/bin/python3 \
#         perl oracle.pl
#
# The dump itself is t/data/oracle.py -- one copy, run by this script and by
# the test, so the frozen answer and the live one cannot drift into being
# answers to different questions.  gemmi 0.7.5.
require 5.010;
use strict;
use warnings FATAL => 'all';
use autodie ':default';
use File::Basename 'dirname';
use Cwd 'abs_path';

my $dir  = dirname(abs_path(__FILE__));
my $py   = $ENV{STRUCTURE_INFO_PYTHON} || 'python3';
my $dump = "$dir/oracle.py";
system("$py -c 'import gemmi' >/dev/null 2>&1") == 0
	or die "$py cannot import gemmi; set STRUCTURE_INFO_PYTHON\n";

opendir(my $dh, $dir);
my @files = sort grep { /\.(?:pdb|ent|cif|mmcif)\z/ } readdir $dh;
closedir $dh;

my $version = qx($py -c 'import gemmi; print(gemmi.__version__)');
chomp $version;

my $out = "$dir/oracle.txt";
open my $fh, '>', "$out.new";
print $fh <<"HEAD";
# gemmi's answer for the structures in this directory, frozen.
#
# Generated by t/data/oracle.pl from t/data/oracle.py with gemmi $version.
# Do not edit: re-run the generator.  t/oracle.t reads this so that the
# comparison against another reader runs on a machine with no python and no
# gemmi, and checks it against the live reader on a machine that has both.
#
# One section per structure: '== <file>' and then gemmi's output, or
# '== <file> refused' for a file gemmi will not read at all, which is a fact
# about the file and is recorded rather than hidden.
HEAD

for my $f (@files) {
	# gemmi refuses a file it cannot make sense of, loudly, and the complaint
	# is worth keeping next to the refusal: pdb1gdr.ent is refused because a
	# 1993 entry leaves its id in the columns gemmi reads a charge from.
	my $err = "$dir/oracle.err.$$";
	my $rows = qx($py \Q$dump\E \Q$dir/$f\E 2>\Q$err\E);
	my $rc = $?;
	open my $eh, '<', $err;
	my @err = <$eh>;
	close $eh;
	unlink $err;
	if ($rc != 0) {
		chomp(my $why = @err ? $err[-1] : 'no reason given');
		$why =~ s/\A\w*(?:Error|Exception): //;
		print $fh "\n== $f refused\n# gemmi: $why\n";
		next;
	}
	$rows =~ s/\A\n//;   # a structure with no atoms prints an empty first line
	print $fh "\n== $f\n$rows";
}
close $fh;
rename "$out.new", $out;
print "wrote $out\n";
