"""
OHSU - ROI utility functions.

TODO - move this to ohsu-qipipe.
"""

import os
import re
import glob
import qiutil


class ROIError(Exception):
    pass


class LesionROI(object):
    """
    Aggregate with attributes :attr:`lesion` :attr:`volume`,
    :attr:`slice` and :attr:`location`.
    """
    def __init__(self, lesion, volume_number, slice_sequence_number,
                 location):
        """
        :param lesion: the :attr:`lesion` value
        :param volume_number: the :attr:`volume` value
        :param slice_sequence_number: the :attr:`slice` value
        :param location: the :attr:`location` value
        """
        self.lesion = lesion
        """The lesion number."""

        self.volume = volume_number
        """The one-based volume number."""

        self.slice = slice_sequence_number
        """The one-based slice sequence number."""

        self.location = location
        """The absolute BOLERO ROI .bqf file path."""

    def __repr__(self):
        return (self.__class__.__name__ +
                str(dict(lesion=self.lesion, volume=self.volume,
                         slice=self.slice, location=self.location)))


PARAM_REGEX = re.compile('(?P<key>\w+)\s*\:\s*(?P<value>\w+)')
"""
The regex to parse a parameter file.
"""


def iter_roi(glob_pat, regex, input_dir):
    """
    Iterates over the the OHSU ROI ``.bqf`` mask files in the given
    input directory. This method is a :class:`LesionROI` generator,
    e.g.::

        >>> # Find .bqf files anywhere under /path/to/session/processing.
        >>> next(iter_roi('processing/*', '.*/\.bqf', '/path/to/session'))
        {lesion: 1, slice: 12, path: '/path/to/session/processing/rois/roi.bqf'}

    :param glob_pat: the glob match pattern
    :;param regex: the file name match regular expression
    :param input_dir: the source session directory to search
    :yield: the :class:`LesionROI` objects
    """
    finder = qiutil.file.Finder(glob_pat, regex)
    for match in finder.match(input_dir):
        file_name = match.group(0)
        # If there is no lesion qualifier, then there is only one lesion.
        try:
            lesion_s = match.group('lesion')
        except IndexError:
            lesion_s = None
        lesion = int(lesion_s) if lesion_s else 1

        # The volume and slice are in the companion parameters file.
        roi_dir, _ = os.path.split(file_name)
        param_file_pat = "%s/*.par" % roi_dir
        param_file_names = glob.glob(param_file_pat)
        if not param_file_names:
            abs_roi_dir = os.path.abspath(roi_dir)
            raise ROIError("The ROI slice directory does not have" +
                           " a parameter file: %s" % abs_roi_dir)
        if len(param_file_names) > 1:
            raise ROIError("The ROI slice directory has more than" +
                           "one parameter file: %s" % roi_dir)
        param_file_name = param_file_names[0]
        params = _collect_parameters(param_file_name)

        # If there is no slice number, then complain.
        slice_seq_nbr_s = params.get('CurrentSlice')
        if not slice_seq_nbr_s:
            raise ROIError("The ROI slice could not be determined from" +
                           " the parameter file: %s" % param_file_name)
        slice_seq_nbr = int(slice_seq_nbr_s)

        # If there is no volume number, then complain.
        volume_nbr_s = params.get('CurrentTimePt')
        if not volume_nbr_s:
            raise ROIError("The ROI volume could not be determined from" +
                           " the parameter file: %s" % param_file_name)
        volume_nbr = int(volume_nbr_s)

        # Prepend the base directory to the matching file path.
        path = os.path.join(input_dir, file_name)

        yield LesionROI(lesion, volume_nbr, slice_seq_nbr,
                        os.path.abspath(path))

def _collect_parameters(s, params):
        params = {}
        with open(param_file_name) as f:
            lines = f.readlines()
            for line in lines:
                match = PARAM_REGEX.match(s)
                if match:
                    params.groups[match.key] = match.value
        return params

@@ -2277,16 +2277,186 @@
 else 1%0A%0A
+        # Prepend the full input directory to the file match.%0A        abs_input_dir = os.path.abspath(input_dir)%0A        file_path = '/'.join(%5Babs_input_dir, file_name%5D)%0A
         
@@ -2552,28 +2552,28 @@
 .split(file_
-name
+path
 )%0A        pa
@@ -2698,59 +2698,8 @@
 es:%0A
-            abs_roi_dir = os.path.abspath(roi_dir)%0A
     
@@ -2816,20 +2816,16 @@
 : %25s%22 %25 
-abs_
 roi_dir)
@@ -3761,262 +3761,287 @@
     
-# Prepend the base directory to the matching file path.%0A        path = os.path.join(input_dir, file_name)%0A%0A        yield LesionROI(lesion, volume_nbr, slice_seq_nbr,%0A                        os.path.abspath(path))%0A%0Adef _collect_parameters(s, params):
+yield LesionROI(lesion, volume_nbr, slice_seq_nbr, file_path)%0A%0Adef _collect_parameters(param_file_name):%0A    %22%22%22%0A    Parses the parameters from the %60%60.par%60%60 file.%0A%0A    :param param_file_name: the paramter file location%0A    :return: the parameter %7Bname: value%7D dictionary
 %0A    
+%22%22%22%0A
     
@@ -4052,20 +4052,16 @@
 ms = %7B%7D%0A
-    
     with
@@ -4097,20 +4097,16 @@
         
-   
- 
 lines = 
@@ -4127,20 +4127,16 @@
         
-    
 for line
@@ -4158,20 +4158,16 @@
         
-  
-  
 match = 
@@ -4184,17 +4184,20 @@
 X.match(
-s
+line
 )%0A      
@@ -4202,20 +4202,16 @@
         
-    
 if match
@@ -4232,36 +4232,54 @@
     
-    params.groups%5Bmatch.key%5D
+key = match.group('key')%0A                value
  = m
@@ -4283,26 +4283,67 @@
 = match.
+group('
 value
+')
 %0A    
+            params%5Bkey%5D = value%0A
     retu

Return absolute file path.