#
# Copyright 2009, Frederic Hornain
# Frederic Hornain <fhornain@gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301  USA

"""
Func MySQL SQL statement module
"""

__author__ = "Frederic Hornain <fhornain@gmail.com>"
__version__ = "0.0.5"
__api_version__ = "0.0.5"
__description__ = "Func MySQL SQL statement module"
__creation_date__ = "03/24/2009"

import func_module
import time
import sys
import service
import re
import MySQLdb
import StringIO
import exceptions
from certmaster.config import read_config
from func.commonconfig import FuncdConfig
from certmaster.config import BaseConfig, Option, IntOption, FloatOption, BoolOption
from func.minion import sub_process

class Mysql(func_module.FuncModule):

    # Update these if need be.
    version = "0.0.5"
    api_version = "0.0.5"
    description = "Func MySQL SQL statement module"
    cursor = ""
    connection = ""

    class Config(BaseConfig):
        user = Option('')
        password = Option('')
        server = Option('')
        database = Option('')

    def __mysql_error_code(self,rc):
        if rc == 0:
            result = "No Error"
	elif rc == 1:
            result = "No MySQL deamon is running on the default MySQL port"
        elif rc == 2:
            result = "No MySQL user, password, server, database have been set in /etc/func/modules/Mysql.conf"
        elif rc == 3:
            result = "Opening MySQL Connection Failed"
        elif rc == 4:
            result = "SQL Statement Failed"
        elif rc == 5:
            result = "Closing MySQL Cursor Failed"
        elif rc == 6:
            result = "Closing MySQL Connection Failed"
        elif rc > 6:
            result = "Unknown Error"
        return result

    def __mysql_config(self):
        if self.options.user == '' or self.options.server == '' or self.options.database == '':
            return 2
        else:
            return 0

    def __mysql_service_status(self):
        mysql_service = service.Service()
        deamon_status = mysql_service.status("mysqld")
        if deamon_status == 0:
            return 0
        else:
            return 1

    def __mysql_open_connection(self,rc):
        if rc == 0:
            rc = self.__mysql_service_status()
        if rc == 0:
            rc = self.__mysql_config()
        if rc == 0:
            try:
                self.connection = MySQLdb.connect (host = self.options.server,
                user = self.options.user,
                passwd = self.options.password,
                db = self.options.database)
            except MySQLdb.Error, e:
                rc = 3
        return rc

    def __mysql_query(self,query,rc):
        h = 0
        i = 0
        k = 0
        records = []
        try:
            self.cursor = self.connection.cursor()
            self.cursor.execute(query)
            while (1):
                row = self.cursor.fetchone()
                if row == None:
                    break
                elementnumber=len(row)
                k = elementnumber-1
                for i in range(elementnumber):
                    if row[i] is None:
                         if i == h :
                             followingelements = row[:k]
                             row = ('none',) + followingelements  
                         elif i > h and i < k:
                             previouselements = row[:i]
                             followingelements = row[i:k]
                             row = previouselements + ('none',) + followingelements
                         elif i == k:
                             previouselements = row[:i]
                             row = previouselements + ('none',)
            	records.append(row)
        except MySQLdb.Error, e:
            rc = 4
        return (records,rc)

    def __mysql_commit(self):
       self.connection.commit()

    def __mysql_close_cursor(self,rc):
        try:
            self.cursor.close()
        except MySQLdb.Error, e:
            rc = 5   
        return rc

    def __mysql_close_connection(self,rc):
        try:
            self.connection.close()
	except MySQLdb.Error, e:
            rc = 6 
        return rc

    def show_config(self):
        """
        Returns the options config
        """
        return self.options

    def change_user(self,changeduser):
        setattr(self.options,"user",changeduser)
        self.save_config()
        return self.options 

    def change_password(self,changedpassword):
        setattr(self.options,'password',changedpassword)
        self.save_config()
        return self.options

    def change_server(self,changedserver):
        setattr(self.options,'server',changedserver)
        self.save_config()
        return self.options

    def change_database(self,changeddatabase):
        setattr(self.options,'database',changeddatabase)
        self.options.database = changeddatabase 
	self.database = self.options.database
	self.Config.database = Option(changeddatabase)
	self.save_config()
        return self.options

    def return_database(self):
        return getattr(self.options, 'database')

    def clear_config(self):
        self.options.user = "root"
        self.options.password = ""
        self.options.server = "localhost"
        self.options.database = "test"
        self.save_config()
        return self.options

    def simple_query(self):
        rc = 0
        query="SELECT VERSION();"
        rc = self.__mysql_open_connection(rc)
        if rc == 0:
            result = self.__mysql_query(query,rc)
            if result[1] == 0: 
                rc = self.__mysql_close_cursor(rc)
            else:
                simplequeryresult = self.__mysql_error_code(rc)
            if rc == 0:
                rc = self.__mysql_close_connection(rc)	
                if rc == 0:
                    simplequeryresult=result[0]
                else:
                    simplequeryresult = self.__mysql_error_code(rc)
            else:
                simplequeryresult = self.__mysql_error_code(rc)
        else:
            simplequeryresult = self.__mysql_error_code(rc)
        return simplequeryresult 
            
    def query(self,query):
        rc = 0
        i = 0
        j = 0
        results_array = []
        temporary_results_array = []
        p = re.compile("\x00")
        rc = self.__mysql_open_connection(rc)
        if rc == 0:
            results = self.__mysql_query(query,rc)
            self.__mysql_commit()
            if results[1] == 0:
                rc = self.__mysql_close_cursor(rc)
            else:
                queryresults = self.__mysql_error_code(rc)
            if rc == 0:
                rc = self.__mysql_close_connection(rc)
                if rc == 0:
                    results_number = len(results)
                    temporary_results = results[0]
                    temporary_results_number = len(temporary_results)
                    for i in range(0,(results_number - 1)):
                      temporary_results = results[i]
                      temporary_results_number = len(temporary_results)
                      for j in range(0,(temporary_results_number)):
                         results = temporary_results[j]  
                         result_string =StringIO.StringIO()
                         result_string.write(results)
                         results = result_string.getvalue()
                         result_string.close()
                         temporary_results_array.append(results)
                      results_array.append(temporary_results_array)   
                    queryresults = results_array
                else:
                    queryresults = self.__mysql_error_code(rc)
            else:
                queryresults = self.__mysql_error_code(rc)
        else:
            queryresults = self.__mysql_error_code(rc)
        return queryresults
