import uuid

from PyDesignData.PyDesignObject import *
from PyDesignData.PyDesignAnalysis import *
from PyDesignData.PyDesignParameter import *
from PyDesignData.PyDesignUOM import *
import os

__author__ = 'magnus'


class PyDesignDocument(PyDesignNamedObject):
    def __init__(self, name, pdid=None):
        self._py_design_objects = {}
        PyDesignNamedObject.__init__(self, name, self, pdid)
        self._analyses = []
        self._reports = []
        self._path = ""
        self._formulas = {}
        self._global_properties = None
        self._changed = False
        self._base_units = []

        if pdid is None:  # New document
            self._global_properties = PyDesignParameters("Global parameters", self)
            self._base_units = PyDesignBaseUnit.create_base_units(self)

    def get_expression(self, name):
        expression = self._global_properties.get_parameter(name)
        if expression is not None:
            return expression
        if name in self._formulas:
            return self._formulas[name]
        return None

    def object_created(self, object):
        """
        :type object: PyDesignObject
        :param object:
        :return:
        """
        self._py_design_objects[object.id] = object
        object.add_listener(self)

    def on_event(self, event):
        self._changed = True

    @property
    def changed(self):
        return self._changed

    @changed.setter
    def changed(self, value):
        self._changed = value

    def get_object(self, pdid):
        """
        :rtype: PyDesignObject
        """
        return self._py_design_objects[pdid]

    def get_analysis(self, index):
        """
        :param index: The index of the analysis to get
        :return: The analysis
        :rtype: PyDesignAnalysis
        """
        return self._analyses[index]

    @property
    def analysis_count(self):
        return len(self._analyses)

    def create_analysis(self, name, type):
        """
        :param name: Name of analysis
        :param type: Type of analysis
        :return: Returns the newly created analysis
        :rtype: PyDesignAnalysis
        """

        analysis = PyDesignAnalysis(name, self, type)
        self.do_event(PyDesignEvent(PyDesignEvent.BeforeItemAddedEvent, self, analysis))
        self._analyses.append(analysis)
        self.do_event(PyDesignEvent(PyDesignEvent.EndItemAddedEvent, self, analysis))
        return analysis

    @property
    def global_parameters(self):
        return self._global_properties

    @property
    def report_count(self):
        return len(self._reports)

    @staticmethod
    def create_id():
        return uuid.uuid1().urn[9:]

    @property
    def path(self):
        return self._path

    @path.setter
    def path(self, value):
        self._path = value

    def undo(self):
        return

    def redo(self):
        return

    def is_modified(self):
        return self._changed

    def object_jsonable(self):
        return {
            "analyses": self._analyses,
            "globalParameters": self._global_properties,
            "reports": self._reports,
            "baseUnits": self._base_units
        }

    @staticmethod
    def deserialize(data):
        """
        :rtype: PyDesignDocument
        :param data:
        :return:
        """
        doc = PyDesignDocument(data["name"], data["id"])
        doc._global_properties = PyDesignParameters.deserialize(doc, data["globalParameters"])
        if "analyses" in data:
            for analysis_data in data["analyses"]:
                analysis = PyDesignAnalysis.deserialize(doc, analysis_data)
                doc._analyses.append(analysis)
        if "baseUnits" in data:
            for base_unit_data in data["baseUnits"]:
                base_unit = PyDesignBaseUnit.deserialize(doc, base_unit_data)
                doc._base_units.append(base_unit)
                # for report_data in data["reports"]:
                # report = PyDesignReport.deserialize(report_data)
                # doc._reports.append(report)
        return doc
