"""Subclass of NewRelation, which is generated by wxFormBuilder."""

import re
import wx
import wxx
from activity.models.ui import ui as ui
import app.resources as rc
import model.cc


# Implementing NewRelation
class RelationDialog(ui.NewRelation):
    """
    This dialog allows to setup a relation between classes
    and/or  instances.
    It's possible to set the cardinalities in the relation, both
    for the parent as for the child, and also the implementation
    method.
    The process of code generation is controlled by xml
    editable plugins and may be customized and expanded.
    """
    @wxx.SetInfo(__doc__)
    def __init__(self, parent, container, to=None):
        """Initialize dialog"""
        super(RelationDialog, self).__init__(parent)
        self._element = container
        self._to = to
        self.project = container.project
        self._hasMinCardFrom = False
        self._hasMaxCardFrom = False
        self._hasMinCardTo = False
        self._hasMaxCardTo = False
        self._minCardFrom = 0
        self._maxCardFrom = -1  # means infinity
        self._minCardTo = 0
        self._maxCardTo = -1  # means infinity
        self.__initClassBoxes__()
        self.m_choice4.SetFocus()
        icon = wx.EmptyIcon()
        icon.CopyFromBitmap(rc.GetBitmap("relation"))
        self.SetIcon(icon)

    def __initClassBoxes__(self):
        """Initialize class boxes"""
        nameFrom = ""
        nameTo = ""
        if type(self._element) is model.cc.Class:
            nameFrom = self._element._name
        if type(self._to) is model.cc.Class:
            nameTo = self._to._name
        classes = self.project(model.cc.Class)
        index1 = wx.NOT_FOUND
        index2 = wx.NOT_FOUND
        for clase in classes:
            i1 = self.m_choice4.Append(clase._name, clase)
            i2 = self.m_choice41.Append(clase._name, clase)
            if clase._name == nameFrom:
                index1 = i1
            if clase._name == nameTo:
                index2 = i2
        if len(nameFrom):
            nameFrom = nameFrom[0].upper() + nameFrom[1:]
        if len(nameTo):
            nameTo = nameTo[0].upper() + nameTo[1:]
        if not index1 == wx.NOT_FOUND:
            self.m_choice4.SetSelection(index1)
            self.m_textCtrl10.SetValue("From" + nameFrom)
        if not index2 == wx.NOT_FOUND:
            self.m_choice41.SetSelection(index2)
            self.m_textCtrl101.SetValue("To" + nameTo)

    def OnChangeFrom(self, event):
        """When changed the from"""
        index = self.m_choice4.GetCurrentSelection()
        name = self.m_choice4.GetString(index)
        name = name[0].upper() + name[1:]
        self.m_textCtrl10.SetValue("From" + name)

    def OnMinCardinalFrom(self, event):
        """Enables or disables from limits"""
        if self.m_chkMinCardFrom.GetValue():
            self.m_minFrom.Enable(True)
            self.m_minFrom.SetValue('1')
        else:
            self.m_minFrom.Enable(False)
        event.Skip()

    def OnMaxCardinalFrom(self, event):
        """Enables or disables from limits"""
        if self.m_chkMaxCardFrom.GetValue():
            self.m_maxFrom.Enable(True)
            self.m_maxFrom.SetValue('infinity')
        else:
            self.m_maxFrom.Enable(False)
        event.Skip()

    def OnMinCardinalTo(self, event):
        """Enables or disables to limits"""
        if self.m_chkMinCardTo.GetValue():
            self.m_minTo.Enable(True)
            self.m_minTo.SetValue('1')
        else:
            self.m_minTo.Enable(False)
        event.Skip()

    def OnMaxCardinalTo(self, event):
        """Enables or disables to limits"""
        if self.m_chkMaxCardTo.GetValue():
            self.m_maxTo.Enable(True)
            self.m_maxTo.SetValue('infinity')
        else:
            self.m_maxTo.Enable(False)
        event.Skip()

    def OnChangeTo(self, event):
        """When changed the to"""
        index = self.m_choice41.GetCurrentSelection()
        name = self.m_choice41.GetString(index)
        name = name[0].upper() + name[1:]
        self.m_textCtrl101.SetValue("To" + name)

    def Validate(self):
        """Validates dialog correctess"""
        self._fromName = self.m_textCtrl10.GetValue()
        self._toName = self.m_textCtrl101.GetValue()
        if re.match("^[A-Za-z_][0-9A-Za-z_]*$", self._fromName) is None:
            wx.MessageBox("From alias contains invalid characters", "Error",
                wx.OK | wx.CENTER | wx.ICON_ERROR, self)
            return False
        if re.match("^[A-Za-z_][0-9A-Za-z_]*$", self._toName) is None:
            wx.MessageBox("To alias contains invalid characters", "Error",
                wx.OK | wx.CENTER | wx.ICON_ERROR, self)
            return False
        index = self.m_choice4.GetCurrentSelection()
        if index is wx.NOT_FOUND:
            return False
        self._from = self.m_choice4.GetClientData(index)
        index = self.m_choice41.GetCurrentSelection()
        if index is wx.NOT_FOUND:
            return False
        self._to = self.m_choice41.GetClientData(index)
        self._critical = self.m_checkBox23.GetValue()
        self._global = self.m_checkBox47.GetValue()
        self._filter = self.m_checkBox24.GetValue()
        self._unique = self.m_checkBox25.GetValue()
        self._unikey = None
        if self.m_chkMinCardFrom.GetValue():
            self._fromMinCardinal = self.m_minFrom.GetValue()
        else:
            self._fromMinCardinal = None
        if self.m_chkMaxCardFrom.GetValue():
            self._fromMaxCardinal = self.m_maxFrom.GetValue()
        else:
            self._fromMaxCardinal = None
        if self.m_chkMinCardTo.GetValue():
            self._toMinCardinal = self.m_minTo.GetValue()
        else:
            self._toMinCardinal = None
        if self.m_chkMaxCardTo.GetValue():
            self._toMaxCardinal = self.m_maxTo.GetValue()
        else:
            self._toMaxCardinal = None
        self._fromAmodeless = self.m_choice12.GetStringSelection()
        self._toAmodeless = self.m_choice121.GetStringSelection()
        self._implementation = self.m_choice19.GetStringSelection()
        self._note = self.m_richText3.GetValue()
        return True

    def get_kwargs(self):
        """returns arguments suitable for instance"""
        return {'fromName': self._fromName, 'toName': self._toName,
            'FROM': self._from, 'TO': self._to, 'critical': self._critical,
            'Global': self._global, 'filter': self._filter, 'unique': self._unique,
            'unikey': self._unikey, 'frommin': self._fromMinCardinal,
            'fommax': self._fromMaxCardinal, 'tomin': self._toMinCardinal,
            'tomax': self._toMaxCardinal, 'fromaccess': self._fromAmodeless,
            'toaccess': self._toAmodeless, 'implementation': self._implementation,
            'note': self._note}

    def OnCancel(self, event):
        """cancel event handler"""
        self.EndModal(wx.ID_CANCEL)

    def CopyAttributes(self, relation):
        """Transfer data to relation items"""
        # as the dialog can be invoked from one side of the relation, we first
        # must access to the relation reference
        if hasattr(relation, '_key'):
            relation = relation._key
        relation._critical = self.m_checkBox23.GetValue()
        relation._global = self.m_checkBox47.GetValue()
        relation._filter = self.m_checkBox24.GetValue()
        relation._unique = self.m_checkBox25.GetValue()
        relation._unikey = None
        relation._implementation = self.m_choice19.GetStringSelection()
        if self.m_chkMinCardFrom.GetValue():
            relation._FROM._minCardinal = self.m_minFrom.GetValue()
        else:
            relation._FROM._minCardinal = None
        if self.m_chkMaxCardFrom.GetValue():
            relation._FROM._maxCardinal = self.m_maxFrom.GetValue()
        else:
            relation._FROM._maxCardinal = None
        if self.m_chkMinCardTo.GetValue():
            relation._TO._minCardinal = self.m_minTo.GetValue()
        else:
            relation._TO._minCardinal = None
        if self.m_chkMaxCardTo.GetValue():
            relation._TO._maxCardinal = self.m_maxTo.GetValue()
        else:
            relation._TO._maxCardinal = None
        relation._FROM._access = self.m_choice12.GetStringSelection()
        relation._TO._access = self.m_choice121.GetStringSelection()
        relation._FROM._name = self.m_textCtrl10.GetValue()
        relation._TO._name = self.m_textCtrl101.GetValue()
        relation.note = self.m_richText3.GetValue()

    def SetAttributes(self, relation):
        """Copy attributes from relation object"""
        # as the dialog can be invoked from one side of the relation, we first
        # must access to the relation reference
        if hasattr(relation, '_key'):
            relation = relation._key
        self.m_checkBox23.SetValue(relation._critical)
        self.m_checkBox47.SetValue(relation._global)
        self.m_checkBox24.SetValue(relation._filter)
        self.m_checkBox25.SetValue(relation._unique)
        if relation._FROM._minCardinal is not None:
            self.m_chkMinCardFrom.SetValue(True)
            self.m_minFrom.Enable()
            self.m_minFrom.SetValue(relation._FROM._minCardinal)
        else:
            self.m_chkMinCardFrom.SetValue(False)
            self.m_minFrom.Enable(False)
            self.m_minFrom.SetValue('0')
        if relation._FROM._maxCardinal is not None:
            self.m_chkMaxCardFrom.SetValue(True)
            self.m_maxFrom.Enable()
            self.m_maxFrom.SetValue(relation._FROM._maxCardinal)
        else:
            self.m_chkMaxCardFrom.SetValue(False)
            self.m_maxFrom.Enable(False)
            self.m_maxFrom.SetValue('infinity')
        if relation._TO._minCardinal is not None:
            self.m_chkMinCardTo.SetValue(True)
            self.m_minTo.Enable()
            self.m_minTo.SetValue(relation._TO._minCardinal)
        else:
            self.m_chkMinCardTo.SetValue(False)
            self.m_minTo.Enable(False)
            self.m_minTo.SetValue('0')
        if relation._TO._maxCardinal is not None:
            self.m_chkMaxCardTo.SetValue(True)
            self.m_maxTo.Enable()
            self.m_maxTo.SetValue(relation._TO._maxCardinal)
        else:
            self.m_chkMaxCardTo.SetValue(False)
            self.m_maxTo.Enable(False)
            self.m_maxTo.SetValue('infinity')
        index = self.m_choice19.FindString(relation._implementation)
        self.m_choice19.SetSelection(index)
        self.m_richText3.SetValue(relation.note)
        index = self.m_choice4.FindString(relation._TO.parent._name)
        self.m_choice4.SetSelection(index)
        index = self.m_choice41.FindString(relation._FROM.parent._name)
        self.m_choice41.SetSelection(index)
        #self.OnChangeFrom(None)
        #self.OnChangeTo(None)
        # once created, relationship cannot be moved this way
        self.m_choice4.Enable(False)
        self.m_choice41.Enable(False)
        self.m_choice12.SetStringSelection(relation._FROM._access)
        self.m_choice121.SetStringSelection(relation._TO._access)
        self.m_textCtrl10.SetValue(relation._FROM._name)
        self.m_textCtrl101.SetValue(relation._TO._name)
        self.SetTitle("Edit relation")

    def OnOK(self, event):
        """Implements OnOK"""
        if self.Validate():
            self.EndModal(wx.ID_OK)
