#!/usr/bin/env python3
"""Exact finite correlations and sampled spectrum for binary sign sequences."""
import argparse
import cmath
import json
import math
from pathlib import Path


def audit(signs,frequency_samples=1024):
    if not isinstance(signs,list) or not signs or not all(type(x) is int and x in (-1,1) for x in signs):
        raise ValueError('signs must be a nonempty list of integer -1/+1 values')
    if type(frequency_samples) is not int or not 4<=frequency_samples<=65536:
        raise ValueError('frequency_samples must be an integer from 4 to 65536')
    n=len(signs)
    if n*frequency_samples>10000000 or n*(n-1)>10000000:
        raise ValueError('Prototype sample or exact-correlation budget exceeded')
    correlations=[sum(signs[i]*signs[i+k] for i in range(n-k)) for k in range(1,n)]
    periodic=[sum(signs[i]*signs[(i+k)%n] for i in range(n)) for k in range(1,n)]
    energy=sum(c*c for c in correlations)
    spectrum=[]
    for j in range(frequency_samples):
        z=cmath.exp(2j*math.pi*j/frequency_samples)
        value=0j
        for coefficient in reversed(signs):value=value*z+coefficient
        spectrum.append(abs(value)/math.sqrt(n))
    # Always include the two real endpoints, even when sample count is odd.
    endpoints=[abs(sum(signs))/math.sqrt(n),abs(sum(s*(-1)**i for i,s in enumerate(signs)))/math.sqrt(n)]
    return dict(length=n,aperiodic_offpeak_correlations=correlations,
                periodic_offpeak_correlations=periodic,
                peak_aperiodic_magnitude=max(map(abs,correlations),default=0),
                barker_peak_condition=max(map(abs,correlations),default=0)<=1,
                zero_periodic_offpeak=all(c==0 for c in periodic),
                merit_factor=n*n/(2*energy) if energy else None,
                merit_factor_infinite=energy==0,correlation_energy_integer=energy,
                sampled_normalized_spectrum_min=min(spectrum+endpoints),
                sampled_normalized_spectrum_max=max(spectrum+endpoints),frequency_samples=frequency_samples,
                correlation_evidence='exact_integer_finite_sequence',spectrum_evidence='floating_point_samples_only',
                whole_circle_flatness_certified=False,new_signing_algorithm=False,
                family_ids=['076','179'],independent_theorem_verification='not_run')


def main():
    parser=argparse.ArgumentParser(description=__doc__)
    parser.add_argument('input',type=Path,help='JSON object with a signs list')
    parser.add_argument('--frequency-samples',type=int,default=1024)
    parser.add_argument('--output',type=Path)
    args=parser.parse_args();record=json.loads(args.input.read_text())
    body=json.dumps(audit(record['signs'],args.frequency_samples),indent=2,allow_nan=False)+'\n'
    if args.output:
        with args.output.open('x') as stream:stream.write(body)
    else:print(body,end='')


if __name__=='__main__':main()
