import sys
sys.dont_write_bytecode = True
import datetime

from adcptool.vector import Vector


#
# some 'constant' values that might be needed
bad_velocity = -32768
bad_discharge = 2147483647
bad_latlong = 30000

#
# handy functions

def line_as_list(f):
    ''' returns a list from the next line of the given file object '''
    return f.pop(0).rstrip('\n').split()


def readnextline(f):
    
    pass
    
    

def print_type(o):
    print(type(o).__name__)
    
    
    
    
class RawProfileObj:
    '''holds general data and all the ensembles'''
    
    def __init__(self, filename):
        self.ensembles = []
        
        # python 3.x vs 2.x
        try:
            self.f = open(filename,'rt', encoding='latin-1').read().split('\n')
        except TypeError:
            self.f = open(filename,'rt').read().split('\n')
        

        #
        # general header stuff
        
        # read something to get warm with python
        self.note1 = self.f.pop(0)
        self.note2 = self.f.pop(0)
        
        l = line_as_list(self.f)
        self.depth_cell_length = float(l[0])
        self.number_of_depth_cells = l[3]
        
        
        #
        # add the ensembles
        i = 0
        while True:
            #print('adding ensemble no',i)            
            self.ensembles.append(EnsembleObj(self.f, self.note1))
            self.f = self.ensembles[i].f

            if len(self.f) <= 1:
                del self.f
                break;
        i += 1
        
        
    def __getstate__(self):
        # Copy the object's state from self.__dict__ which contains
        # all our instance attributes. Always use the dict.copy()
        # method to avoid modifying the original state.
        state = self.__dict__.copy()
        # Remove the unpickabel entries.
        #del state['f']
        return state
        
        
class EnsembleObj:
    '''
    holds an ensemble (set of different measurements on the same
    (river surface) position
    '''
    def __init__(self, f, note1):
    
        self.f = f
        self.cells = []
        
        #
        # ensemble header stuff
        
    
        firstline =  self.f.pop(0)
        
        # test if this line is actually what we want
        if firstline == note1 or len(firstline) == 0:
            exit('error: it looks like there are multiple transsects (profiles) in one ASCII file! (or there is an empty line in it which should never happen)')
            
        else:
            l = firstline.rstrip('\n').split()

        time = [int(i) for i in l[0:7]]
        
        time[0] += 2000  # in the source, they start counting in year 2000
        time[6] *= 10000 # 1/100 seconds to microseconds
        
        # compile time to python time format
        self.ens_time = datetime.datetime(time[0], time[1], time[2], time[3], time[4], time[5], time[6])
        
        self.ens_number = int(l[7])
        self.corrected_heading = float(l[12])
        
        # line "2"
        l = line_as_list(self.f)

        self.depth_reading = [float(i) for i in l[8:12]]

        # line "3"
        l = line_as_list(self.f)
        self.total_elapsed_distance = float(l[0])
        self.total_elapsed_time = float(l[1])
        self.total_distance_traveled_north = float(l[2])
        self.total_distance_traveled_east = float(l[3])
        self.total_distance_made_good = float(l[4])
        
        
        # skip line "4"
        l = line_as_list(self.f)
        self.lat = float(l[0])
        self.lon = float(l[1])

        # skip line "5"
        l = line_as_list(self.f)

        
        # line "6"
        l = line_as_list(self.f)
        
        self.measurement_units = l[1] # the units only apply to the velocity apparently
        self.number_of_cells = int(l[0])
        self.number_of_good_cells = 0
        
        
        
        #
        # add the bins/cells
        
        for i in range(self.number_of_cells):
            i = len(self.cells)
            
            self.cells.append(CellObj(self.f))
            self.f = self.cells[i].f
            
            
            if self.cells[i].cell_is_good:
                self.number_of_good_cells += 1
            else:
                # remove broken cells again
                self.cells.pop()
                    
                
    def __getstate__(self):
        # Copy the object's state from self.__dict__ which contains
        # all our instance attributes. Always use the dict.copy()
        # method to avoid modifying the original state.
        state = self.__dict__.copy()
        # Remove the unpicklable entries.
        #del state['f']
        return state
        
        
class CellObj:
    ''' holds the actual measured data '''
    def __init__(self, f):
        self.f = f
        l = line_as_list(self.f)
        
        if float(l[1]) != -32768:
            self.cell_is_good = True
            self.depth = float(l[0])
            self.velocity_magn = float(l[1])
            self.velocity_dir = float(l[2])
            self.velocity_comp = Vector([float(i) for i in l[3:6]])
            self.velocity_error = float(l[6])
            self.percent_good = float(l[11])
        else:
            self.cell_is_good = False
        
    def __getstate__(self):
        # allows the class to be pickled
        state = self.__dict__.copy()
        # Remove the unpicklable entries.
        #del state['f']
        return state
        