#!/usr/bin/env python3

"""
Download ENDF/B-VII.1 ENDF data from NNDC for photo-atomic and atomic
relaxation data and convert it to an HDF5 library for use with OpenMC.
This data is used for photon transport in OpenMC.
"""

import os
import sys
import shutil
import zipfile
import argparse
from io import BytesIO
from urllib.request import urlopen

import openmc.data


class CustomFormatter(argparse.ArgumentDefaultsHelpFormatter,
                      argparse.RawDescriptionHelpFormatter):
    pass

parser = argparse.ArgumentParser(
    description=__doc__,
    formatter_class=CustomFormatter
)
parser.add_argument('-c', '--cross-sections',
                    help='cross_sections.xml file to append libraries to')
args = parser.parse_args()

base_url = 'http://www.nndc.bnl.gov/endf/b7.1/zips/'
files = ['ENDF-B-VII.1-photoat.zip', 'ENDF-B-VII.1-atomic_relax.zip']
block_size = 16384

# ==============================================================================
# DOWNLOAD FILES FROM NNDC SITE

if not os.path.exists('photon_hdf5'):
    os.mkdir('photon_hdf5')

for f in files:
    # Establish connection to URL
    url = base_url + f
    req = urlopen(url)

    # Get file size from header
    file_size = req.length
    downloaded = 0

    # Check if file already downloaded
    if os.path.exists(f):
        if os.path.getsize(f) == file_size:
            print('Skipping ' + f)
            continue
        else:
            overwrite = input('Overwrite {}? ([y]/n) '.format(f))
            if overwrite.lower().startswith('n'):
                continue

    # Copy file to disk
    print('Downloading {}... '.format(f), end='')
    with open(f, 'wb') as fh:
        while True:
            chunk = req.read(block_size)
            if not chunk: break
            fh.write(chunk)
            downloaded += len(chunk)
            status = '{0:10}  [{1:3.2f}%]'.format(
                downloaded, downloaded * 100. / file_size)
            print(status + chr(8)*len(status), end='')
        print('')

# ==============================================================================
# EXTRACT FILES

for f in files:
    print('Extracting {0}...'.format(f))
    zipfile.ZipFile(f).extractall()

# ==============================================================================
# GENERATE HDF5 DATA LIBRARY

# If previous cross_sections.xml was specified, load it in
if args.cross_sections is not None:
    lib_path = args.cross_sections
    library = openmc.data.DataLibrary.from_xml(lib_path)
else:
    lib_path = os.path.join('photon_hdf5', 'cross_sections.xml')
    library = openmc.data.DataLibrary()

for z in range(1, 101):
    element = openmc.data.ATOMIC_SYMBOL[z]
    print('Generating HDF5 file for Z={} ({})...'.format(z, element))

    # Generate instance of IncidentPhoton
    photo_file = os.path.join('photoat', 'photoat-{:03}_{}_000.endf'.format(z, element))
    atom_file = os.path.join('atomic_relax', 'atom-{:03}_{}_000.endf'.format(z, element))
    f = openmc.data.IncidentPhoton.from_endf(photo_file, atom_file)

    # Write HDF5 file and register it
    hdf5_file = os.path.join('photon_hdf5', element + '.h5')
    f.export_to_hdf5(hdf5_file, 'w')
    library.register_file(hdf5_file)

library.export_to_xml(lib_path)
