# -*- coding: utf-8

import xml.etree.ElementTree as ET
import numpy as np
from .roi import Roi


class ComplexRoi(Roi):
    """
    Represents a ROI that is a set of more elementary simple ROIs
    """

    __parent = None
    __roi_list = None

    def __init__(self, parent, name, subroi_list):
        """
        Initializes the subroi list.

        Arguments:
            parent - The ROI list
            name - name of the complex ROI
            subroi_list - list of all subroi names
        """
        self.__parent = parent
        self.set_name(name)
        self.set_subroi_list(subroi_list)

    def set_subroi_list(self, subroi_list):
        self.__roi_list = []
        for subroi in subroi_list:
            self.__roi_list.append(self.__parent[subroi])

    def get_subroi_list(self):
        """
        Returns list of all sub-roi's
        """
        return self.__roi_list

    def get_left(self):
        """
        Returns the left border of the ROI
        """
        left = None
        for roi in self.__roi_list:
            if left is None or roi.get_left() < left:
                left = roi.get_left()
        return left

    def get_right(self):
        """
        Returns the right border of the ROI
        """
        right = None
        for roi in self.__roi_list:
            if right is None or roi.get_right() > right:
                right = roi.get_right()
        return right

    def get_top(self):
        """
        Returns the top border of the ROI
        """
        top = None
        for roi in self.__roi_list:
            if top is None or roi.get_top() < top:
                top = roi.get_top()
        return top

    def get_bottom(self):
        """
        Returns the bottom border of the ROI
        """
        bottom = None
        for roi in self.__roi_list:
            if bottom is None or roi.get_bottom() > bottom:
                bottom = roi.get_bottom()
        return bottom

    def get_width(self):
        """
        Returns the ROI width
        """
        x = np.zeros(self.get_right()) != 0
        for roi in self.__roi_list:
            for coordinates in roi.get_coordinate_list():
                x[coordinates[1]] = True
        return x.sum()

    def get_height(self):
        """
        Returns the ROI height
        """
        y = np.zeros(self.get_bottom()) != 0
        for roi in self.__roi_list:
            for coordinates in roi.get_coordinate_list():
                y[coordinates[0]] = True
        return y.sum()

    def get_coordinate_list(self):
        """
        Returns the list of all coordinates
        """
        m = np.zeros((self.get_bottom(), self.get_right())) != 0
        for roi in self.__roi_list:
            for coordinates in roi.get_coordinate_list():
                m[coordinates[0], coordinates[1]] = True
        lst = []
        for i in range(m.shape[0]):
            for j in range(m.shape[1]):
                if m[i, j]:
                    lst.append((i, j))
        return lst

    def get_area(self):
        """
        Returns the total area of the ROI
        """
        m = np.zeros((self.get_bottom(), self.get_right())) != 0
        for roi in self.__roi_list:
            for coordinates in roi.get_coordinate_list():
                m[coordinates[0], coordinates[1]] = True
        return m.sum()

    def get_type(self):
        return "complex"

    def _save_details(self, xml):
        xml.attrib['type'] = "complex"
        for roi in self.__roi_list:
            element = ET.SubElement(xml, "subroi")
            element.text = roi.get_name()
            element.tail = "\n"

    def apply(self, data_map):
        """
        Applies ROI to the map

        Input arguments:
            data_map - numpy array
        """
        mask = np.zeros((data_map.shape[0], data_map.shape[1])) == 0
        for coordinate in self.get_coordinate_list():
            mask[coordinate[0], coordinate[1]] = False
        new_map = np.array(data_map, dtype=np.float)
        new_map[mask] = np.nan
        new_map = new_map[self.get_top():self.get_bottom(), self.get_left():self.get_right()]
        return new_map

# -*- coding: utf-8

import xml.etree.ElementTree as ET
import numpy as np
from .roi import Roi


class ComplexRoi(Roi):
    """
    Represents a ROI that is a set of more elementary simple ROIs
    """

    __parent = None
    __roi_list = None

    def __init__(self, parent, name, subroi_list):
        """
        Initializes the subroi list.

        Arguments:
            parent - The ROI list
            name - name of the complex ROI
            subroi_list - list of all subroi names
        """
        self.__parent = parent
        self.set_name(name)
        self.set_subroi_list(subroi_list)

    def set_subroi_list(self, subroi_list):
        self.__roi_list = []
        for subroi in subroi_list:
            self.__roi_list.append(self.__parent[subroi])

    def get_subroi_list(self):
        """
        Returns list of all sub-roi's
        """
        return self.__roi_list

    def get_left(self):
        """
        Returns the left border of the ROI
        """
        left = None
        for roi in self.__roi_list:
            if left is None or roi.get_left() < left:
                left = roi.get_left()
        return left

    def get_right(self):
        """
        Returns the right border of the ROI
        """
        right = None
        for roi in self.__roi_list:
            if right is None or roi.get_right() > right:
                right = roi.get_right()
        return right

    def get_top(self):
        """
        Returns the top border of the ROI
        """
        top = None
        for roi in self.__roi_list:
            if top is None or roi.get_top() < top:
                top = roi.get_top()
        return top

    def get_bottom(self):
        """
        Returns the bottom border of the ROI
        """
        bottom = None
        for roi in self.__roi_list:
            if bottom is None or roi.get_bottom() > bottom:
                bottom = roi.get_bottom()
        return bottom

    def get_width(self):
        """
        Returns the ROI width
        """
        x = np.zeros(self.get_right()) != 0
        for roi in self.__roi_list:
            for coordinates in roi.get_coordinate_list():
                x[coordinates[1]] = True
        return x.sum()

    def get_height(self):
        """
        Returns the ROI height
        """
        y = np.zeros(self.get_bottom()) != 0
        for roi in self.__roi_list:
            for coordinates in roi.get_coordinate_list():
                y[coordinates[0]] = True
        return y.sum()

    def get_coordinate_list(self):
        """
        Returns the list of all coordinates
        """
        m = np.zeros((self.get_bottom(), self.get_right())) != 0
        for roi in self.__roi_list:
            for coordinates in roi.get_coordinate_list():
                m[coordinates[0], coordinates[1]] = True
        lst = []
        for i in range(m.shape[0]):
            for j in range(m.shape[1]):
                if m[i, j]:
                    lst.append((i, j))
        return lst

    def get_area(self):
        """
        Returns the total area of the ROI
        """
        m = np.zeros((self.get_bottom(), self.get_right())) != 0
        for roi in self.__roi_list:
            for coordinates in roi.get_coordinate_list():
                m[coordinates[0], coordinates[1]] = True
        return m.sum()

    def get_type(self):
        return "complex"

    def _save_details(self, xml):
        xml.attrib['type'] = "complex"
        for roi in self.__roi_list:
            element = ET.SubElement(xml, "subroi")
            element.text = roi.get_name()
            element.tail = "\n"

    def apply(self, data_map):
        """
        Applies ROI to the map

        Input arguments:
            data_map - numpy array
        """
        mask = np.zeros((data_map.shape[0], data_map.shape[1])) == 0
        for coordinate in self.get_coordinate_list():
            mask[coordinate[0], coordinate[1]] = False
        new_map = np.array(data_map, dtype=np.float)
        new_map[mask] = np.nan
        new_map = new_map[self.get_top():self.get_bottom(), self.get_left():self.get_right()]
        return new_map

# -*- coding: utf-8 Represents a ROI that is a set of more elementary simple ROIs Initializes the subroi list.          Arguments:             parent - The ROI list             name - name of the complex ROI             subroi_list - list of all subroi names Returns list of all sub-roi's Returns the left border of the ROI Returns the right border of the ROI Returns the top border of the ROI Returns the bottom border of the ROI Returns the ROI width Returns the ROI height Returns the list of all coordinates Returns the total area of the ROI Applies ROI to the map          Input arguments:             data_map - numpy array