# @package      hubzero-submit-server
# @file         MySQLiteDatabase.py
# @copyright    Copyright (c) 2012-2020 The Regents of the University of California.
# @license      http://opensource.org/licenses/MIT MIT
#
# Copyright (c) 2012-2020 The Regents of the University of California.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
# HUBzero is a registered trademark of The Regents of the University of California.
#
import time
import sqlite3
import logging
import traceback

from hubzero.submit.LogMessage import getLogIDMessage as getLogMessage

class MySQLiteDatabase:
   def __init__(self,
                activeJobDBPath,
                activeJobDumpPath):
      self.logger        = logging.getLogger(__name__)

      self.activeJobDBPath   = activeJobDBPath
      self.activeJobDumpPath = activeJobDumpPath
      self.dbConnection      = None
      self.cursor            = None
      self.connected         = False
      self.userVersion       = None


   def getDBuserVersion(self):
      userVersion = 0
      self.cursor.execute("PRAGMA user_version")
      row = self.cursor.fetchone()
      if row:
         userVersion = row[0]

      return(userVersion)


   def setDBuserVersion(self,
                        userVersion):
      self.cursor.execute("PRAGMA user_version = %d" % (userVersion))
      self.commit()
      self.userVersion = userVersion
      self.logger.log(logging.INFO,getLogMessage("SQLite database updated to user_version = %d" % (self.userVersion)))


   def connect(self):
      if not self.connected:
         try:
            self.dbConnection = sqlite3.connect(self.activeJobDBPath)
            self.dbConnection.row_factory = sqlite3.Row
            self.cursor = self.dbConnection.cursor()
            self.userVersion = self.getDBuserVersion()
            self.logger.log(logging.INFO,getLogMessage("SQLite user_version = %d" % (self.userVersion)))
            self.connected = True
         except sqlite3.Error as e:
            self.logger.log(logging.ERROR,getLogMessage("Error creating sqlite connection %s." % (e.args[0])))
         except:
            self.logger.log(logging.ERROR,getLogMessage(traceback.format_exc()))

      return(self.connected)


   def commit(self):
      if self.dbConnection:
         self.dbConnection.commit()


   def disconnect(self):
      if self.dbConnection:
         self.dbConnection.close()
         self.dbConnection = None
         self.cursor = None
         self.connected = False


   def close(self):
      if self.dbConnection:
         self.dbConnection.close()
         self.dbConnection = None
         self.cursor = None
         self.connected = False


   def select(self,
              sqlCommand,
              sqlParameters=None):
#     self.logger.log(logging.DEBUG,getLogMessage(sqlCommand))
      result = ()
      try:
         if sqlParameters:
            count = self.cursor.execute(sqlCommand,sqlParameters)
         else:
            count = self.cursor.execute(sqlCommand)
         result = self.cursor.fetchall()
      except sqlite3.Error as e:
         self.logger.log(logging.ERROR,getLogMessage("%s.  SQL was: %s" % (e.args[0],sqlCommand)))
      except:
         self.logger.log(logging.ERROR,getLogMessage("Some other SQL exception."))

      return(result)


   def update(self,
              sqlCommand,
              sqlParameters=None):
#     self.logger.log(logging.DEBUG,getLogMessage(sqlCommand))
      result = ""
      try:
         if sqlParameters:
            count = self.cursor.execute(sqlCommand,sqlParameters)
         else:
            count = self.cursor.execute(sqlCommand)
      except sqlite3.Error as e:
         result = e.args[0]

      return(result)


   def insert(self,
              sqlCommand,
              sqlParameters=None):
#     self.logger.log(logging.DEBUG,getLogMessage(sqlCommand))
      result = ""
      try:
         if sqlParameters:
            count = self.cursor.execute(sqlCommand,sqlParameters)
         else:
            count = self.cursor.execute(sqlCommand)
         result = self.cursor.rowcount
      except sqlite3.Error as e:
         result = e.args[0]

      return(result)


   def delete(self,
              sqlCommand,
              sqlParameters=None):
#     self.logger.log(logging.DEBUG,getLogMessage(sqlCommand))
      result = ""
      try:
         if sqlParameters:
            count = self.cursor.execute(sqlCommand,sqlParameters)
         else:
            count = self.cursor.execute(sqlCommand)
         result = self.cursor.rowcount
      except sqlite3.Error as e:
         result = e.args[0]

      return(result)


   def script(self,
              sqlScript):
#     self.logger.log(logging.DEBUG,getLogMessage(sqlScript))
      result = ""
      try:
         count = self.cursor.executescript(sqlScript)
      except sqlite3.Error as e:
         result = e.args[0]

      return(result)


   def dump(self):
      if self.dbConnection:
         try:
            fpDumpFile = open(self.activeJobDumpPath,'w')
            try:
               fpDumpFile.write("PRAGMA user_version = %d;\n" % (self.userVersion))
               for line in self.dbConnection.iterdump():
                   fpDumpFile.write('%s\n' % (line))
            except (IOError,OSError):
               pass
            finally:
               fpDumpFile.close()
         except (IOError,OSError):
            pass


