from enum import Enum
from string import Template

"""
Для генерации текстового формата pen ГИС Аксиома trtp.
По образцу документации "Формат стилей линий ГИС Аксиома".
"""


class TrtpExport:
    def __str__(self):
        return self.to_string()

    def to_string(self):
        order = [] if self.__orderhack__() is None else self.__orderhack__()
        result = ""
        template_obj = Template("""
            $obj {
                $field
            } \n""")
        template_param = Template("$a1 : $a2 \n")
        d = self.__dict__
        od = order if len(order) > 0 else d
        for k in od:
            if d[k] is not None:
                if type(d[k]) in (int, float, bool, str):
                    result += template_param. \
                        substitute(a1=k, a2='"{}"'.format(d[k]) if type(d[k]) == str else d[k])
                elif isinstance(d[k], list):
                    field = "\n".join(["element : {}".format(param) for param in d[k]])
                    result += template_obj.substitute(obj=k, field=field)
                else:
                    result += template_obj.substitute(obj=k, field=d[k])
        return result

    def __orderhack__(self):
        return []


class UnitValue:
    def __init__(self, value, unit):
        self.unit = unit
        self.value = value

    def __str__(self):
        return Template("""
            value : $v
            unit  : $u 
        """).substitute(v=self.value, u=self.unit.value)


class Unit(Enum):
    px = '"px"'
    pt = '"pt"'
    mm = '"mm"'
    cm = '"cm"'


class DefaultColor(TrtpExport):
    def __init__(self, color):
        self.color = color


class JoinStyle(Enum):
    MiterJoin = 0
    BevelJoin = 64
    RoundJoin = 128

    #  SvgMiterJoin  ?

    def __str__(self):
        return str(self.value)


class CapStyle(Enum):
    FlatCap = 0
    SquareCap = 16
    RoundCap = 32

    def __str__(self):
        return str(self.value)


class BaseField(TrtpExport):
    """Базовые поля"""

    def __init__(self):
        self.enabled = None
        """Позволяет отключить отображение элемента."""
        self.useStyleColor = True
        """
        Если true, то цвет элемента определяется пользователем, 
        если false, то цвет фиксированный и берется из defaultColor.
        """
        self.defaultColor = DefaultColor(int("0xff000000", 0))
        """Фиксированный цвет элемента (QColor)."""
        self.useStyleWidth = True
        """
        Если true, то толщина линий определяется пользователем,
        если false, то цвет фиксированный и берется из defaultWidth.
        """
        self.baseWidth = 1
        """Реальная толщина рассчитывается как пользовательская_толщина * baseWidth."""
        self.defaultWidth = UnitValue(1, Unit.px)
        """Фиксированная толщина линии."""
        self.opacity = 1
        """Непрозрачность линии. 1.0 - полностью непрозрачная линия, 0.0 - невидимая линия."""
        self.joinStyle = JoinStyle.BevelJoin
        """Стиль соединения - определяет, как будет происходить соединение двух сегментов."""
        self.capStyle = CapStyle.FlatCap  # заказчик рекомендации FlatCap
        """Стиль окончания - определяет, как будут отрисовываться окончания линий."""

    def __orderhack__(self):
        return ["enabled", "useStyleColor", "defaultColor", "useStyleWidth",
                "baseWidth", "defaultWidth", "opacity", "joinStyle", "capStyle"]


class MainLine(BaseField):
    """Основная линия"""

    def __init__(self):
        super().__init__()
        self.dashPattern = []
        """
        Определяет длины штрихов и промежутков между ними в единицах, соответствующих ширине линии. 
        Задаётся последовательностью пар чисел: длина штриха - длина промежутка.
        """
        self.dashOffset = 0
        """Определяет смещение пунктира относительно начала линии."""
        self.offset = 0
        """Определяет перпендикулярное смещение рисуемой линии относительно точек отображаемой геометрической фигуры."""

    def __orderhack__(self):
        return super().__orderhack__() + ["dashPattern", "dashOffset", "offset"]


class OutLine(BaseField):
    """Обвотка"""

    def __init__(self):
        super().__init__()


class CommonMarker(BaseField):
    def __init__(self):
        super().__init__()
        self.fill = True
        self.path = ""

    def __orderhack__(self):
        return super().__orderhack__() + ["fill", "path"]


class BeginMarker(CommonMarker):
    def __init__(self):
        super().__init__()


class EndMarker(CommonMarker):
    def __init__(self):
        super().__init__()


class ContinuousMarker(CommonMarker):
    def __init__(self):
        super().__init__()
        self.dashPattern = []
        self.dashOffset = 0
        self.bend = True

    def __orderhack__(self):
        return super().__orderhack__() + ["dashPattern", "dashOffset", "bend"]


class MapInfoSubPattern(TrtpExport):
    def __init__(self):
        self.mainLine = MainLine()
        self.outline = None
        self.beginMarker = None
        self.endMarker = None
        self.continuousMarker = None

    def __str__(self):
        return "mapInfoSubPattern {" + \
            self.to_string() + \
            "\n}"

    def __orderhack__(self):
        return super().__orderhack__() + ["mainLine", "outline", "beginMarker", "endMarker", "continuousMarker"]

    @staticmethod
    def empty_pattern():
        msp = MapInfoSubPattern()
        msp.mainLine.enabled = False
        return msp
