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

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


# Implementing NewClass
class ClassDialog(ui.NewClass):
    """
    This dialog allows to create a new class or struct. Even as top
    element or nested in anoter project container. You can specify
    access for child classes and structs. Serialize flag indicates
    the creation and mainteinance of serialization methods for the
    class.
    """
    @wxx.SetInfo(__doc__)
    def __init__(self, parent, container):
        """Initialice dialog"""
        super(ClassDialog, self).__init__(parent)
        self.m_textCtrl2.SetFocus()
        self._container = container
        self.project = container.project
        self._original = ""
        self._template = None
        self._template_types = []
        self._is_external = False
        icon = wx.EmptyIcon()
        icon.CopyFromBitmap(rc.GetBitmap("class"))
        self.SetIcon(icon)
        self.m_textCtrl2.SetFocus()
        if container.inner_class:
            self.m_staticText88.Enable()
            self.m_choice2.Enable()

    def OnToggleTemplate(self, event):
        """Handles toggle event"""
        if self.m_checkBox61.GetValue():
            self.m_stStartTemplate.Enable(True)
            self.m_template.Enable(True)
            self.m_stEndTemplate.Enable(True)
        else:
            self.m_stStartTemplate.Enable(False)
            self.m_template.SetValue('')
            self.m_template.Enable(False)
            self.m_stEndTemplate.Enable(False)
        event.Skip()

    def OnChangeTemplateSpecification(self, event):
        """Handles change text event"""
        text = self.m_template.GetValue()
        l = text.split(',')
        prologs = ['class', 'typename']
        r = []
        for u in l:
            v = u.split('=')[0].strip()
            for p in prologs:
                if v.find(p) == 0:
                    v = v.replace(p, '').strip()
                    if len(v):
                        r.append(v.strip())
                    break
        # set templates to available types
        self._template_types = r
        event.Skip()

    def OnToggleExternalClass(self, event):
        """Handle the external flag"""
        self._is_external = self.m_checkBox90.GetValue()
        self.m_checkBox60.Enable(not self._is_external)
        event.Skip()

    def Validate(self):
        """implement OnOK button"""
        self._name = self.m_textCtrl2.GetValue()
        if len(self._name) == 0:
            wx.MessageBox("Class name must be non empty", "Error",
                wx.OK | wx.CENTER | wx.ICON_ERROR, self)
            return False
        if re.match("^[A-Za-z_][0-9A-Za-z_]*$", self._name) is None:
            wx.MessageBox("class name contains invalid characters", "Error",
                wx.OK | wx.CENTER | wx.ICON_ERROR, self)
            return False
        if not self._original == self._name:
            if self._name in [x._name for x in self.project.level_classes]:
                wx.MessageBox("Class already exist", "Error",
                    wx.OK | wx.CENTER | wx.ICON_ERROR, self)
                return False
        self._is_struct = self.m_checkBox83.GetValue()
        self._note = self.m_richText3.GetValue()
        self._memberPrefix = self.m_textPrefix.GetValue()
        if self.m_checkBox61.GetValue():
            self._template = self.m_template.GetValue()
        else:
            self._template = None
        self._access = self.m_choice2.GetStringSelection()
        return True

    def CopyAttributes(self, cls):
        """Copy dialog selections to object"""
        cls._is_external = self._is_external
        cls._name = self._name
        cls._is_struct = self._is_struct
        cls.note = self._note
        cls._memberPrefix = self._memberPrefix
        cls._template = self._template
        cls._template_types = self._template_types
        cls._access = self._access

    def SetAttributes(self, clase):
        """Copy object attributes to dialog"""
        self.SetTitle("Edit class/struct")
        #backward compatibility code - to simplfy in newer versions
        if not hasattr(clase, '_is_external'):
            clase._is_external = False
        self._is_external = clase._is_external
        self._original = clase._name
        self._name = clase._name
        self._note = clase.note
        self._is_struct = clase._is_struct
        self._memberPrefix = clase._memberPrefix
        self._template = clase._template
        self._template_types = clase._template_types
        self.m_textCtrl2.SetValue(self._name)
        self.m_checkBox83.SetValue(self._is_struct)
        self.m_textPrefix.SetValue(self._memberPrefix)
        self.m_richText3.SetValue(self._note)
        self._access = clase._access
        if clase.parent.inner_class:
            self.m_staticText88.Enable()
            self.m_choice2.Enable()
            i = self.m_choice2.FindString(self._access)
            self.m_choice2.Select(i)

        if clase._template is not None:
            self.m_stStartTemplate.Enable(True)
            self.m_template.Enable(True)
            self.m_stEndTemplate.Enable(True)
            self.m_checkBox61.SetValue(True)
            self.m_template.SetValue(self._template)
            # if template is specified and some contained method /argument holds
            # some of the template types, the template specification cannot be changed
            self.SetTitle("Edit class")
            for method in clase(model.cc.MemberMethod):
                if method._typei._type_alias in clase._template_types:
                    self.m_checkBox61.Enable(False)
                    self.m_checkBox61.SetToolTipString(
                        'Template cannot be edited because some method is using this template types.')
                    self.m_stStartTemplate.Enable(False)
                    self.m_template.Enable(False)
                    self.m_stEndTemplate.Enable(False)
                    return
            for arg in clase(model.cc.Argument):
                if arg._typei._type_alias in clase._template_types:
                    self.m_checkBox61.Enable(False)
                    self.m_checkBox61.SetToolTipString(
                        'Template cannot be edited because some argument is using this template types.')
                    self.m_stStartTemplate.Enable(False)
                    self.m_template.Enable(False)
                    self.m_stEndTemplate.Enable(False)
                    return
        self.m_checkBox90.SetValue(self._is_external)

    def get_kwargs(self):
        """Returns suitable arguments for creating object"""
        kwargs = {}
        kwargs['parent'] = self._container
        kwargs['name'] = self._name
        kwargs['is_struct'] = self._is_struct
        kwargs['access'] = self._access
        kwargs['template'] = self._template
        kwargs['template_types'] = self._template_types
        kwargs['prefix'] = self._memberPrefix
        kwargs['note'] = self._note
        kwargs['is_external'] = self._is_external
        return kwargs

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