from __future__ import division
import logging

from allensdk.core.simple_tree import SimpleTree

from run_tissuecyte_unionize_classic import get_ancestor_id_map, get_volume_scale
from allensdk.internal.mouse_connectivity.interval_unionize.cav_unionizer import CavUnionizer
import data_utilities as du


def run(input_data):

    logging.info('making ancestor id map')
    ancestor_id_map = get_ancestor_id_map(input_data['structures'])

    logging.info('computing volume scale factor')
    volume_scale = (input_data['reference_spacing'] / 10 ** 3) ** 3 # mum3 -> mm3
    logging.info('volume scale factor : {0}'.format(volume_scale))

    logging.info('reference shape : {0}'.format(input_data['reference_shape']))
    logging.info('reference spacing : {0}'.format(input_data['reference_spacing']))
    logging.info('image_series_id : {0}'.format(input_data['image_series_id']))

    annotation = du.load_annotation(input_data['annotation_path'], input_data['grid_paths']['data_mask'])

    unionizer = CavUnionizer()
    unionizer.setup_interval_map(annotation)
    del annotation

    signal_arrays = du.get_cav_density(input_data['grid_paths']['cav_density'])
    signal_arrays.update(du.get_sum_pixels(input_data['grid_paths']['sum_pixels']))

    for k, v in signal_arrays.iteritems():
        logging.info('sorting {0} array'.format(k))
        signal_arrays[k] = v.flat[unionizer.sort]
    
    logging.info('computing unionizes from directly annotated voxels')
    raw_unionizes = unionizer.direct_unionize(signal_arrays, pre_sorted=True)
    
    logging.info('propagating data to ancestor structures')
    raw_unionizes = CavUnionizer.propagate_unionizes(raw_unionizes, ancestor_id_map)

    logging.info('propagating data to bilateral unionizes')
    bilateral = CavUnionizer.propagate_to_bilateral(raw_unionizes)

    cooked_unionizes = unionizer.postprocess_unionizes(raw_unionizes, 
                                                       image_series_id=input_data['image_series_id'], 
                                                       volume_scale=volume_scale)
    cooked_bilateral = unionizer.postprocess_unionizes(bilateral, 
                                                       image_series_id=input_data['image_series_id'], 
                                                       volume_scale=volume_scale)

    for item in cooked_bilateral:
        item['hemisphere'] = '(none)'
        cooked_unionizes.append(item)

    logging.info('computed {0} unionize records'.format(len(cooked_unionizes)))
    return cooked_unionizes
