'''
This module contains helper functions for timedata classes.
'''

from __future__ import(
	division,
	print_function,
	)

__docformat__ = 'restructuredtext en'
__all__ = ['_rpo_extract_tg']

import numpy as np
import pandas as pd

from scipy.interpolate import interp1d

#import exceptions
from .exceptions import(
	FileError,
	)

#define function to extract variables from .csv file
def _rpo_extract_tg(file, nt, bl_subtract = True):
	'''
	Extracts time, temperature, and carbon remaining vectors from `all_data`
	file generated by NOSAMS RPO LabView program.

	Parameters
	----------
	file : str or pd.DataFrame
		File containing isotope data, either as a path string or a
		dataframe.

	nt : int 
		The number of time points to use.

	bl_subtract : Boolean
		Tells the program whether or not to linearly subtract the baseline
		such that ppm CO2 returns to 0 at the beginning and end of the run. 
		Treats baseline as linear from the average of the first 100 points in
		CO2 to the average of the last 100 points in CO2. Defaults to`True`.

	Returns
	-------
	g : np.ndarray
		Array of the true fraction of carbon remaining at each timepoint.
		Length `nt`.
	
	t : np.ndarray
		Array of time, in seconds. Length `nt`.

	T : np.ndarray
		Array of temperature, in Kelvin. Length `nt`.

	Raises
	------
	FileError
		If `file` is not str or ``pd.DataFrame`` instance.
	
	FileError
		If index of `file` is not ``pd.DatetimeIndex`` instance.

	FileError
		If `file` does not contain "CO2_scaled" and "temp" columns.

	Notes
	-----
	Noisy data, especially at the beginning of the run, could lead to `g`
	values slightly outside of the (0, 1) range (*i.e.* noisy ppm CO2 less than
	zero could lead to slightly negative `g`). This method removes this
	possibility by enforcing that all values of `g` are within (0, 1).

	'''

	#check data format and raise appropriate errors
	if isinstance(file, str):
		#import as dataframe
		file = pd.read_csv(
			file,
			index_col = 0,
			parse_dates = True)

	elif not isinstance(file, pd.DataFrame):
		raise FileError(
			'file must be pd.DataFrame instance or path string')

	if 'CO2_scaled' and 'temp' not in file.columns:
		raise FileError(
			'file must have "CO2_scaled" and "temp" columns')

	elif not isinstance(file.index, pd.DatetimeIndex):
		raise FileError(
			'file index must be pd.DatetimeIndex instance')

	#extract necessary data
	secs_m = (file.index - file.index[0]).seconds
	CO2_m = file.CO2_scaled
	T_m = file.temp

	#before continuing, thermogram must be linearly interpolated to deal
	# with missing data (e.g. if data deleted during data clea-up).
	# Version: 0.1.3., bug noticed by Cristina Subt (SFU).

	#make array of 1-second deltas
	secs = np.arange(0,np.max(secs_m))

	#make CO2 function and interpolate
	fsm = interp1d(secs_m, CO2_m)
	CO2 = fsm(secs)

	#make Temp function and interpolate
	ftm = interp1d(secs_m, T_m)
	Temp = ftm(secs)

	#stop Version 0.1.3. bug fix here.

	#linearly subtract baseline if required
	if bl_subtract is True:
		#calculate initial and final bl
		bl0 = np.average(CO2[:100])
		blf = np.average(CO2[-100:])

		#subtract linear baseline
		npt = len(CO2)
		bl = bl0 + (blf - bl0)*np.arange(0, npt)/npt

		CO2 = CO2 - bl

	#calculate total CO2
	tot = np.sum(CO2)

	#calculate alpha
	alpha = np.cumsum(CO2)/tot

	#assert that alpha remains between 0 and 1 (noisy data at the beginning 
	# and end of the run could lead to alpha *slightly* outside fo this range)
	alpha[alpha > 1.0] = 1.0
	alpha[alpha < 0.0] = 0.0

	#generate t array
	t0 = secs[0]; tf = secs[-1]
	dt = (tf-t0)/nt

	#make downsampled points at midpoint
	t = np.linspace(t0, tf, nt + 1) + dt/2 
	
	#drop last point since it's beyond tf
	t = t[:-1] 

	#generate functions to down-sample
	fT = interp1d(secs, Temp)
	fg = interp1d(secs, alpha)
	
	#create downsampled arrays
	T = fT(t) + 273.15 #convert to K
	g = 1-fg(t)

	return g, t, T

