# @author dumitru.fostic@ypg.com
# @date   May , 2014
import MySQLdb
import warnings
import pytest


class MysqlConnector(object):
    """
    Connects to MySQL DB, executes queries
    Autocommit is disabled by default, commit is done with commit function
    Warnings are turned into exceptions
    """
    def __init__(self, config_data):
        """
        Initialize DB connection. Turning warning into exceptions
        """
        warnings.filterwarnings('error', category=MySQLdb.Warning)  # turn warnings into exceptions
        self.db = None
        try:
            self.db = MySQLdb.connect(**config_data)
            self.cursor = self.db.cursor(MySQLdb.cursors.DictCursor)
            self.db.autocommit(False)   # in case of autocommit will change by default ot ON in future
        except MySQLdb.Error, err:
            print "Error %d: %s" % (err.args[0], err.args[1])
            pytest.fail('FAILED connecting to DB with error: %d: %s' % (err.args[0], err.args[1]))

    def get_autocommit_status(self, var_type='local'):
        """
        Returns status of autocommit LOCAL/GLOBAL/SESSION variables (local by default)
        :return: tuple(dict) i.e. ({'Value': 'OFF', 'Variable_name': 'autocommit'},)
        """
        if (var_type in ('local', 'global', 'session')) is False:
            pytest.fail("Wrong argument '%s' passed in <get_auto_commit> function. Valid args are str: 'local', 'global' or 'session'" % var_type)

        status_query = "show " + var_type + " variables where variable_name = 'autocommit'"
        return self.select_query(status_query)

    def select_query(self, query, fetch='all'):
        """
        Send/execute queries
        :param: str MySQL query
        :param: str 'one'/'all' Rows to be fetched
        :return: fetch = one  dictionary i.e. {row_1}
        :return: fetch != one tuple with arguments dictionaries, each dictionary is a row i.e. ({row_first}, {row_second}, ... ,{row_last})
        """
        try:
            self.cursor.execute(query)
            data = self.cursor.fetchone() if fetch == 'one' else self.cursor.fetchall()
            return data
        except MySQLdb.Error, err:
            print "Error %d: %s" % (err.args[0], err.args[1])
            pytest.fail('<select_query()> function FAILURE with error: %d: %s' % (err.args[0], err.args[1]))

    def update_query(self, query):
        """
        Sends query to DB.
        :param: str query
        :return: int Nr of rows updated (in case of updating with same value, query is successful but nr of rows updated  = 0
        """
        try:
            self.cursor.execute(query)
            rows_updated = self.cursor.rowcount
            print "Number of rows updated: %s" % rows_updated
        except MySQLdb.Error, err:
            print "Error %d: %s" % (err.args[0], err.args[1])
            pytest.fail('<update_query()> function FAILURE with error: %d: %s' % (err.args[0], err.args[1]))

        return rows_updated

    def delete_query(self, query):
        """
        to be updated: don't have permission to delete on current working DB
        """
        try:
            self.cursor.execute(query)
            rows_deleted = self.cursor.rowcount
            print "Number of rows deleted: %s" % rows_deleted
        except MySQLdb.Error, err:
            print "Error %d: %s" % (err.args[0], err.args[1])
            pytest.fail('<delete_query()> function FAILURE with error: %d: %s' % (err.args[0], err.args[1]))

        return rows_deleted

    def commit(self):
        self.db.commit()

    def rollback(self):
        self.db.rollback()

    def close_cursor(self):
        self.cursor.close()

    def close_db(self):
        self.db.close()

    def __del__(self):
        self.cursor.close()
        self.db.close()

