from xml.etree import ElementTree as ET

from openmc.checkvalue import *


class Trigger(object):

    def __init__(self, trigger_type, threshold):

        # Initialize Mesh class attributes
        self.trigger_type = trigger_type
        self.threshold = threshold
        self._scores = []


    def __deepcopy__(self, memo):

        existing = memo.get(id(self))

        # If this is first time we have tried to copy this object, create a copy
        if existing is None:

            clone = type(self).__new__(type(self))
            clone._trigger_type = self._trigger_type
            clone._threshold = self._threshold

            clone._scores = []
            for score in self._scores:
                clone.add_score(score)

            memo[id(self)] = clone

            return clone

        # If this object has been copied before, return the first copy made
        else:
            return existing


    @property
    def trigger_type(self):
        return self._trigger_type


    @property
    def threshold(self):
        return self._threshold


    @property
    def scores(self):
        return self._scores


    @trigger_type.setter
    def trigger_type(self, trigger_type):

        if not trigger_type in ['variance', 'std_dev', 'rel_err']:
            msg = 'Unable to create a tally trigger with ' \
                  'type "{0}"'.format(trigger_type)
            raise ValueError(msg)

        self._trigger_type = trigger_type


    @threshold.setter
    def threshold(self, threshold):

        if not is_float(threshold):
            msg = 'Unable to set a tally trigger threshold with ' \
                  'threshold "{0}"'.format(threshold)
            raise ValueError(msg)

        self._threshold = threshold


    def add_score(self, score):

        if not is_string(score):
            msg = 'Unable to add score "{0}" to tally trigger since ' \
                  'it is not a string'.format(score)
            raise ValueError(msg)

        # If the score is already in the Tally, don't add it again
        if score in self._scores:
            return
        else:
            self._scores.append(score)


    def __repr__(self):

        string = 'Trigger\n'
        string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self._trigger_type)
        string += '{0: <16}{1}{2}\n'.format('\tThreshold', '=\t', self._threshold)
        string += '{0: <16}{1}{2}\n'.format('\tScores', '=\t', self._scores)
        return string


    def get_trigger_xml(self, element):

        subelement = ET.SubElement(element, "trigger")
        subelement.set("type", self._trigger_type)
        subelement.set("threshold", str(self._threshold))

        # Scores
        if len(self._scores) != 0:

            scores = ''
            for score in self._scores:
                scores += '{0} '.format(score)

            scores.rstrip(' ')
            subelement.set("scores", scores)
