#!/usr/bin/env python3
#
# https://www.wayforward.net/geomag/compile-cof
# Copyright(c) 2005, 2008, 2022 Wayforward LLC
#
# ---
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
# USA
#
# ---
# Compiles COF files, downloadable from
#	https://www.ngdc.noaa.gov/geomag/WMM/
# as provided by NGDC, into static data linkable into C programs.
#
# Example:
#	$ ./compile-cof *.COF >wmm.c
#
"""Compile .COF files included in geomag releases from the NGDC into
C data files.
"""

USAGE = """\
Usage: python3 compile-cof {input .COF file} ...
"""

from sys import argv, exit, stderr

models = []

def main(args):
    if len(args) == 0:
        print(USAGE, file=stderr)
        exit(1)

    for fn in args:
        with open(fn) as f:
            read_batch(f)

    print('/**************************')
    print(' * AUTOMATICALLY GENERATED')
    print(' * To re-create, run', ' '.join(argv))
    print(' */')
    print('#include "av_geo.h"')
    print()

    for model in models:
        print('const struct GeoData %s[] = {' % model['name'])
        for line in model['data']:
             print('\t{ %8.1ff, %8.1ff, %8.1ff, %8.1ff },' % line)
        print('};')
        print()

    models.sort(key=lambda x: x['year_min'])

    print()
    print('const struct GeoModel GEO_MODELS[] = {')

    for model in models:
        print('\t{ %(year_min)6.1ff, %(year_max)6.1ff, %(alt_min)6.1ff, %(alt_max)6.1ff, %(count)3d, %(a)3d, %(b)3d, %(name)s },' % model)

    print('};')
    print()
    print('const unsigned GEO_MODEL_COUNT = sizeof(GEO_MODELS) / sizeof(GEO_MODELS[0]);')

def read_batch(f):
    header = next(f)

    a = header.split()

    if len(a) == 11:
        read_v1(f, a)

    elif len(a) == 3:
        read_v2(f, a)

def read_v1(f, a):
    name = a[0].replace('-', '_')
    year = float(a[1])
    count = int(a[2])
    an = int(a[3])
    am = int(a[4])
    year_min = float(a[5])
    year_max = float(a[6])
    alt_min = float(a[7])
    alt_max = float(a[8])
    name1 = a[9].replace('-', '_')
    lineno = int(a[10])

    assert name == name1
    assert lineno == 0
    assert year >= year_min

    data = []

    for n in range(1, count + 1):
        for m in range(n + 1):
            a = next(f).split()
            lineno += 1

            assert n == int(a[0])
            assert m == int(a[1])

            x = float(a[2])
            y = float(a[3])
            z = float(a[4])
            t = float(a[5])

            data.append( (x, y, z, t) )

            # DGRF2005 != IGRF2005, just the one exception
            #assert name1 == a[6]

            assert lineno == int(a[7])

    if year_min >= 2000.0:
        models.append(dict(year_min=year_min, year_max=year_max,
                           alt_min=alt_min, alt_max=alt_max,
                           name=name, count=count, a=an, b=0, data=data))

    return True

def read_v2(f, a):
    year = float(a[0])
    name = a[1].replace('-', '_')

    data = []
    for line in f:
        a = line.split()

        if len(a) == 1:
            break

        n = int(a[0])
        m = int(a[1])

        x = float(a[2])
        y = float(a[3])
        z = float(a[4])
        t = float(a[5])

        data.append( (x, y, z, t) )

    models.append(dict(year_min=year, year_max = year+5,
                       alt_min=-1, alt_max=600,
                       name=name, count=m, a=m, b=0, data=data))

if __name__ == '__main__':
    main(argv[1:])
