from __future__ import division
import logging

import numpy as np
from six import iteritems

from .interval_unionizer import IntervalUnionizer
from .tissuecyte_unionize_record import TissuecyteInjectionUnionize, \
    TissuecyteProjectionUnionize

  
class TissuecyteUnionizer(IntervalUnionizer):
    '''A specialization of the IntervalUnionizer set up for unionizing 
    Tissuecyte-derived projection data.
    '''
    

    @classmethod
    def record_cb(cls):
        return {'injection': TissuecyteInjectionUnionize(), 
                'projection': TissuecyteProjectionUnionize()}
    
    
    def extract_data(self, data_arrays, low, high):
        '''As parent
        '''
    
        unionize = self.__class__.record_cb()

        unionize['injection'].calculate(low, high, data_arrays)
        unionize['projection'].calculate(low, high, data_arrays, unionize['injection'])
        
        return unionize 
        
    
    @classmethod                
    def propagate_record(cls, child_record, ancestor_record, copy_all=False):
        '''As parent
        '''

        for k, v in child_record.iteritems():
            v.propagate(ancestor_record[k], copy_all)
        
        return ancestor_record
        

    def postprocess_unionizes(self, raw_unionizes, image_series_id, 
                              output_spacing_iso, volume_scale, target_shape, sort):
        '''As parent
        
        New Parameters
        --------------
        output_spacing_iso : numeric
            Isometric spacing of reference space in microns
        volume_scale : numeric
            Scale factor mapping pixels to microns^3
        target_shape : array-like of numeric
            Shape of reference space
        
        '''

        unionizes = []
        total_injection_volume = 0
        
        logging.info('getting formatted unionize output')
        for sid, un in raw_unionizes.iteritems():
            
            if sid < 0:
                hemisphere = 1
            else:
                hemisphere = 2
                
            current = []
            for ij, item in iteritems(un):    
            
                v = item.output(output_spacing_iso, volume_scale, target_shape, sort)
                injection = True if ij == 'injection' else False
                
                if injection and hemisphere != 3:
                    total_injection_volume += v['direct_projection_volume']
                    
                del v['direct_projection_volume']
                del v['direct_sum_projection_pixels']
            
                v.update({'is_injection': injection, 
                          'hemisphere_id': hemisphere, 
                          'structure_id': abs(sid), 
                          'image_series_id': image_series_id})
                          
                current.append(v)
                
            unionizes.extend(current)
        
        if total_injection_volume > 0:
            logging.info('computing normalized projection volume')
            for un in unionizes:
                un['normalized_projection_volume'] = un['projection_volume'] / total_injection_volume
        else:
            logging.warning('no injection found!')
            for un in unionizes:
                un['normalized_projection_volume'] = 0
            
        return filter(lambda x: x['sum_pixels'] > 0, unionizes)

    
    

    
