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

import os, wx, wxx, app
import app.resources as rc
from ctx import localcontext as context


# Implementing NewProject
class ProjectDialog(app.NewProject):
    """
    This dialog is the start point for a new project to
    be created. You  may select the target language and
    set his common options. The language may be set only
    before the project is created.
    """
    @wxx.SetInfo(__doc__)
    def __init__(self, parent, container=None):
        """Initialization"""
        super(ProjectDialog, self).__init__(parent)
        stdPaths = wx.StandardPaths.Get()
        self._container = container
        # if this project is inside workspace, the base
        # path must be determined by this workspace
        wk = container.workspace
        if wk is not None:
            self._base = wk._dir
            self.m_bpButton3.Enable(False)
            self.m_textCtrl9.SetEditable(False)
            self.m_bpButton3.Enable(False)
        else:
            self._base = stdPaths.GetDocumentsDir()
        self.m_textCtrl9.SetValue(self._base)
        self.app = context.app
        self._original = ""
        self._autodir = True
        self._veto = False
        self.m_textCtrl1.SetFocus()
        icon = wx.EmptyIcon()
        icon.CopyFromBitmap(rc.GetBitmap('cppproject'))
        self.SetIcon(icon)
        self._database_host = ''
        self._database_user = ''
        self._database_password = ''

    def CopyAttributes(self, prj):
        """Update project attributes with dialog values"""
        sel = self.m_choicebook1.GetSelection()
        prj._name = self._name
        if sel == 0:
            prj._language = 'c++'
        elif sel == 1:
            prj._language = 'python'
        elif sel == 2:
            prj._language = 'databases'
        prj._dir = self._dir
        if sel in [0, 1]:
            prj._includeDir = self.m_textCtrl23.GetValue()
            prj._srcDir = self.m_textCtrl24.GetValue()
            prj._useMaster = self.m_checkBox52.GetValue()
            prj._masterInclude = self.m_textCtrl25.GetValue()
            prj._author = self.m_textCtrl251.GetValue()
            prj._date = self.m_datePicker1.GetValue().FormatISODate()
            if self.m_checkBox53.IsChecked():
                prj._license = self.m_choice16.GetStringSelection()
            else:
                prj._license = None
            prj._type = self.m_choice151.GetStringSelection()
            prj._version[0] = self.m_spinCtrl11.GetValue()
            prj._version[1] = self.m_spinCtrl21.GetValue()
            prj._version[2] = self.m_spinCtrl31.GetValue()
            prj._useMakefile = self.m_checkBox54.IsChecked()
            prj.note = self.m_richText13.GetValue()
        else:
            handler = prj._handler
            handler._database_host = self._database_host
            handler._database_user = self._database_user
            handler._database_password = self._database_password
            handler._database_default = self._database_default

    def SetAttributes(self, prj):
        """Set dialog attributes based on existing project"""
        if prj._language == 'c++':
            self.m_choicebook1.SetSelection(0)
        elif prj._language == 'python':
            self.m_choicebook1.SetSelection(1)
        elif prj._language == 'databases':
            self.m_choicebook1.SetSelection(2)
        self._veto = True
        self.m_textCtrl1.SetValue(prj._name)
        self.m_textCtrl9.SetValue(prj._dir)
        if prj._language in ['c++', 'python']:
            self.m_textCtrl23.SetValue(prj._includeDir)
            self.m_textCtrl24.SetValue(prj._srcDir)
            self.m_checkBox52.SetValue(prj._useMaster)
            self.m_textCtrl25.Enable(prj._useMaster)
            self.m_textCtrl25.SetValue(prj._masterInclude)
            self.m_textCtrl251.SetValue(prj._author)
            date = wx.DateTime()
            date.ParseDate(prj._date)
            self.m_datePicker1.SetValue(date)
            if prj._license is not None:
                self.m_checkBox53.SetValue(True)
                self.m_choice16.SetStringSelection(prj._license)
            else:
                self.m_checkBox53.SetValue(False)
            self.m_choice151.SetStringSelection(prj._type)
            self.m_spinCtrl11.SetValue(prj._version[0])
            self.m_spinCtrl21.SetValue(prj._version[1])
            self.m_spinCtrl31.SetValue(prj._version[2])
            self.m_checkBox54.SetValue(prj._useMakefile)
            self.m_richText13.SetValue(prj.note)
        elif prj._language == 'databases':
            handler = prj._handler
            self.m_textCtrl252.SetValue(handler._database_host)
            self.m_textCtrl231.SetValue(handler._database_user)
            self.m_textCtrl241.SetValue(handler._database_password)
            self.m_comboBox1.SetValue(handler._database_default)
        self._original = prj._name
        self.SetTitle("Edit project")

    def OnPageChanged(self, event):
        """Show/Hide some controls from project type"""
        sel = event.GetSelection()
        icon = wx.EmptyIcon()
        if  sel == 2:
            # This is a database project
            self.m_panel6.Hide()
            self.m_panel7.Hide()
            icon.CopyFromBitmap(rc.GetBitmap('databases'))
        else:
            self.m_panel6.Show()
            self.m_panel7.Show()
            if sel == 0:
                icon.CopyFromBitmap(rc.GetBitmap('cppproject'))
            elif sel == 1:
                icon.CopyFromBitmap(rc.GetBitmap('python'))
        self.fgSizer4.Layout()
        self.fgSizer65.Layout()
        self.SetIcon(icon)

    def OnPageChanging(self, event):
        """Checks if project type can be changed"""
        if self._veto:
            event.Veto()
        else:
            event.Skip()

    def OnChangeProjectName(self, event):
        """Process change text event"""
        if self._autodir:
            name = self.m_textCtrl1.GetValue()
            #create a custom subdirectory
            self.m_textCtrl9.SetValue(os.path.join(self._base, name))
            if self.m_checkBox52.GetValue():
                #replace master include
                name = name.replace(" ", "_")
                name += ".h"
                self.m_textCtrl25.SetValue(name)

    def OnChooseDir(self, event):
        """Launch subdialog for choosing dir"""
        dialog = wx.DirDialog(self, "Select directory",
            self.m_textCtrl9.GetValue(), wx.DD_DIR_MUST_EXIST)
        if dialog.ShowModal() == wx.ID_OK:
            self.m_textCtrl9.SetValue(dialog.GetPath())
            self._autodir = False

    def OnToggleMasterInclude(self, event):
        """Toggle using master include file"""
        if self.m_checkBox52.GetValue():
            self.m_textCtrl25.Enable(True)
            self.m_textCtrl25.SetValue(self.m_textCtrl1.GetValue() + ".h")
        else:
            self.m_textCtrl25.Enable(False)

    # Database project handlers
    def on_mysql_host_change(self, event):
        """Handle database host change"""
        self._database_host = self.m_textCtrl252.GetValue()
        self.UpdateTestDatabaseConnection()

    def on_mysql_user_change(self, event):
        """Handle user host change"""
        self._database_user = self.m_textCtrl231.GetValue()
        self.UpdateTestDatabaseConnection()

    def on_mysql_password_change(self, event):
        """Handle user password change"""
        self._database_password = self.m_textCtrl241.GetValue()
        self.UpdateTestDatabaseConnection()

    def UpdateTestDatabaseConnection(self):
        """Update the enabled/disabled status of the test connection button"""
        if len(self._database_host) > 0 and len(self._database_user) > 0 and len(self._database_password) > 0:
            self.m_button3.Enable(True)
        else:
            self.m_button3.Enable(False)

    def OnTestDatabaseConnection(self, event):
        """Test the database connection"""
        if self.TestDatabaseConnection():
            self.UpdateSchemas()

    def GetMySQLdbDriver(self):
        """Attempt to import MySQLdb and return status"""
        try:
            import MySQLdb
        except:
            return False
        return MySQLdb

    def TestDatabaseConnection(self, verbose=True):
        """Check the database connectivity"""
        retry = False
        driver = self.GetMySQLdbDriver()
        if not driver:
            reponse = wx.MessageBox("\nThe mysql-python package is not installed.\n\n"
                "You need have installed python-dev and libmysqlclient-dev \n"
                "and mysql-python package. For example doing:\n\n"
                " > sudo apt-get install python-dev libmysqlclient-dev \n"
                " > (sudo) pip install mysql-python.\n\n"
                "Do you want we attempt to install mysql-python for you?",
                "Error", wx.YES_NO | wx.CENTER | wx.ICON_ERROR, context.frame)
            if reponse != wx.YES:
                return
            if os.system("gksudo 'apt-get -y install python-dev libmysqlclient-dev'"):
                wx.MessageBox("Install failed!", "Error", wx.OK | wx.CENTER | wx.ICON_ERROR, context.frame)
                return
            if os.system("pip install mysql-python"):
                #Ok, now with sudo
                if os.system("gksudo 'pip install mysql-python'"):
                    wx.MessageBox("Install failed!", "Error", wx.OK | wx.CENTER | wx.ICON_ERROR, context.frame)
                    return
            retry = True
        if retry:
            driver = self.GetMySQLdbDriver()
            if driver:
                wx.MessageBox("The install seems ok, but import mysql-python still fails.\n"
                "Try to close and reope beatle.\n"
                "Sorry for the inconvenience", "Error", wx.OK | wx.CENTER | wx.ICON_ERROR, context.frame)
                return
        try:
            conn = driver.connect(host=self._database_host,
                        user=self._database_user,
                        passwd=self._database_password)
        except driver.Error:
            wx.MessageBox("Connection failed.", "Error", wx.OK | wx.CENTER | wx.ICON_ERROR, context.frame)
            return False
        conn.close()
        if verbose:
            wx.MessageBox("Connection success.", "Error", wx.OK | wx.CENTER | wx.ICON_ERROR, context.frame)
        return True

    def UpdateSchemas(self):
        """Update the schema list"""
        driver = self.GetMySQLdbDriver()
        conn = driver.connect(host=self._database_host, user=self._database_user, passwd=self._database_password)
        conn.query('SHOW SCHEMAS')
        data = conn.store_result()
        schemas = []
        for i in range(0, data.num_rows()):
            schemas.append(data.fetch_row()[0][0])
        del data
        conn.close()
        self.m_comboBox1.Clear()
        self.m_comboBox1.AppendItems(schemas)

    def Validate(self):
        """Validate dialog"""
        sel = self.m_choicebook1.GetSelection()
        if sel == 0:
            self._language = 'c++'
        elif sel == 1:
            self._language = 'python'
        elif sel == 2:
            self._language = 'databases'
        self._name = self.m_textCtrl1.GetValue()
        if len(self._name) == 0:
            wx.MessageBox("Project name must be non empty", "Error",
                wx.OK | wx.CENTER | wx.ICON_ERROR, self)
            return False
        if not self._original == self._name:
            if self.app.ExistProject(self._name) is True:
                wx.MessageBox("Project already exist", "Error",
                    wx.OK | wx.CENTER | wx.ICON_ERROR, self)
                return False
        self._dir = self.m_textCtrl9.GetValue()
        if len(self._dir) == 0:
            wx.MessageBox("Target directory must be non empty",
                "Error", wx.OK | wx.CENTER | wx.ICON_ERROR, self)
            return False
        if sel in [0, 1]:
            # python and c++
            if self.m_checkBox52.GetValue():
                if len(self.m_textCtrl25.GetValue()) == 0:
                    wx.MessageBox("Master include must be non empty",
                        "Error", wx.OK | wx.CENTER | wx.ICON_ERROR, self)
                    return False
            self._includeDir = self.m_textCtrl23.GetValue()
            self._srcDir = self.m_textCtrl24.GetValue()
            self._useMaster = self.m_checkBox52.GetValue()
            self._masterInclude = self.m_textCtrl25.GetValue()
            self._author = self.m_textCtrl251.GetValue()
            self._date = self.m_datePicker1.GetValue().FormatISODate()
            self._license = self.m_choice16.GetStringSelection()
            self._type = self.m_choice151.GetStringSelection()
            self._version = []
            self._version = [
                self.m_spinCtrl11.GetValue(),
                self.m_spinCtrl21.GetValue(),
                self.m_spinCtrl31.GetValue()]
            self._useMakefile = True
        else:
            self._database_host = self.m_textCtrl252.GetValue()
            self._database_user = self.m_textCtrl231.GetValue()
            self._database_password = self.m_textCtrl241.GetValue()
            self._database_default = self.m_comboBox1.GetValue()
            if not self.TestDatabaseConnection(False):
                return False
        return True

    def get_kwargs(self):
        """returns arguments for instance... pending"""
        kwargs = {
            'parent': self._container,
            'language': self._language,
            'name': self._name,
            'dir': self._dir,
        }
        if self._language in ['c++', 'python']:
            kwargs.update({
                'includedir': self._includeDir,
                'sourcedir': self._srcDir,
                'usemaster': self._useMaster,
                'masterinclude': self._masterInclude,
                'author': self._author,
                'date': self._date,
                'license': self._license,
                'type': self._type,
                'version': self._version,
                'usemakefile': self._useMakefile
            })
        elif self._language == 'databases':
            kwargs.update({
                'database_host': self._database_host,
                'database_user': self._database_user,
                'database_password': self._database_password,
                'database_default': self._database_default,
            })
        return kwargs

    # Handlers for NewProject events.
    def OnOK(self, event):
        """Handle ok button"""
        if self.Validate():
            self.EndModal(wx.ID_OK)


