#!/usr/bin/env python3
"""rstool is an open source command-line program for reading and converting
native radiosonde data to NetCDF and calculation of derived physical quantities.

Usage: rstool <input_type> <output_type> <input> <output>

Arguments:

- `input_type` - See Input types below.
- `output_type` - See Output types below.
- `input` - Input file or directory.
- `output` - Output file (NetCDF).

Input types:

- `imet` - InterMet Systems iMet-1-ABxn. `input` should be the 
    directory generated by the iMetOS-II software.
- `ws` - Windsond. `input` should be the `.sounding` file generated by the
    Windsond software.
- `raw:<instrument>` - "Raw" instrument-dependent format (NetCDF). `instrument`
    is one of `imet`, `ws`.
- `pts` - Collection of measurement points (NetCDF). The output of running
    rstool with the output type `pts`.
- `prof` - Profile (prof) dataset.

Output types:

- `raw` - "Raw" instrument-dependent format (NetCDF).
- `pts` - Collection of measurement points (NetCDF).
- `prof` - Vertical profile calculated by interpolating the measurement points
    during the ascent of the radiosonde as a function of height (NetCDF).
- `prof:desc` - The same as `prof`, but for the descent.
"""

import sys
import signal
signal.signal(signal.SIGINT, lambda signal, frame: sys.exit(0))

VERSION = '0.1.0'

import datetime as dt
import numpy as np
import ds_format as ds
import aquarius_time as aq

import rstoollib
from rstoollib.drivers import DRIVERS
from rstoollib.headers import HEADER_PTS, HEADER_PROF
from rstoollib import postprocess, prof

def get_driver(name):
	try:
		drv = DRIVERS[name]
	except KeyError:
		raise ValueError('%s: unknown input type' % name)
	return drv
	
def main(input_type, output_type, input_, output, surf=None):
	d_raw = None
	d_pts = None
	d_prof = None
	d_prof_desc = None
	d_surf = None
	desc = False

	not_supported_msg = 'input or output type not supported'

	if input_type.startswith('raw:'):
		name = input_type[(input_type.index(':')+1):]
		drv = get_driver(name)
		d_raw = ds.read(input_)
	elif input_type == 'pts':
		d_pts = ds.read(input_)
	elif input_type == 'prof':
		d_prof = ds.read(input_)
	else:
		drv = get_driver(input_type)
		#if output_type == 'prof' and hasattr(drv, 'read_prof'):
		#	d_prof = drv.read_prof(input_)
		if hasattr(drv, 'read'):
			d_raw = drv.read(input_)

	if d_pts is None and d_raw is not None and hasattr(drv, 'pts'):
		d_pts = drv.pts(d_raw)

	if d_prof is None and d_pts is not None:
		d_prof = prof(d_pts)
		d_prof_desc = prof(d_pts, desc=True)

	if d_prof is not None and surf is not None:
		drv = rstoollib.drivers.surf
		d_surf = drv.read(surf, d_prof['time'][0])
		if d_surf is not None:
			for k, v in d_surf.items():
				if k != '.':
					d_prof[k] = d_surf[k]

	if d_prof is not None:
		postprocess(d_prof)
	
	if d_prof_desc is not None:
		postprocess(d_prof_desc)

	if output_type == 'prof':
		if d_prof is None:
			raise ValueError(not_supported_msg)
		d = d_prof
	elif output_type == 'prof:desc':
		if d_prof_desc is None:
			raise ValueError(not_supported_msg)
		d = d_prof_desc
	elif output_type == 'pts':
		if d_pts is None:
			raise ValueError(not_supported_msg)
		d = d_pts
	elif output_type == 'raw':
		if d_raw is None:
			raise ValueError(not_supported_msg)
		d = d_raw
	else:
		raise ValueError(not_supported_msg)

	d['.'] = d.get('.', {})
	d['.']['.'] = d['.'].get('.', {})
	d['.']['.'].update({
		'software': 'rstool ' + VERSION + \
			' (https://github.com/peterkuma/rstool)',
		'created': aq.to_iso(aq.from_datetime(dt.datetime.utcnow())),
	})
	ds.write(output, d)

if __name__ == '__main__':
	if len(sys.argv) not in [5, 6]:
		sys.stderr.write(sys.modules[__name__].__doc__)
		sys.exit(1)

	input_type = sys.argv[1]
	output_type = sys.argv[2]
	if len(sys.argv) == 5:
		surf = None
		input_ = sys.argv[3]
		output = sys.argv[4]
	elif len(sys.argv) == 6:
		input_ = sys.argv[3]
		surf = sys.argv[4]
		output = sys.argv[5]

	np.seterr(all='ignore')

	#try:
	main(input_type, output_type, input_, output, surf=surf)
	#except Exception as e:
	#	sys.stderr.write('%s: %s\n' % (sys.argv[0], str(e)))
	#	sys.exit(1)
