using System;
using System.Data.SQLite;

namespace BulkPrinting
{
    public class DBHelper: IDisposable
    {
        private SQLiteConnection _connection;
        private object _writeLock = new object();
        private bool isDisposed = false;

        public DBHelper(string dataSource, byte[] password)
        {
            _connection = new SQLiteConnection(dataSource);
            _connection.SetPassword(password);
            _connection.Open();
        }

        public SQLiteTransaction BeginTransaction()
        {
            return _connection.BeginTransaction();
        }

        public void Close()
        {
            _connection.Close();
        }

        public SQLiteCommand CreateCommand()
        {
            return new SQLiteCommand(_connection);
        }

        public SQLiteCommand CreateCommand(SQLiteTransaction transaction, params SQLiteParameter[] parameters)
        {
            var command = new SQLiteCommand();
            command.Transaction = transaction;
            foreach (var parameter in parameters)
            {
                command.Parameters.Add(parameter);
            }
            return command;
        }

        public SQLiteCommand CreateCommand(string commandText, SQLiteTransaction transaction = null)
        {
            return new SQLiteCommand(commandText, _connection, transaction);
        }

        public SQLiteCommand CreateCommand(string commandText, params SQLiteParameter[] parameters)
        {
            var command = new SQLiteCommand(commandText, _connection);
            foreach (var parameter in parameters)
            {
                command.Parameters.Add(parameter);
            }
            return command;
        }

        protected virtual void Dispose(bool disposing)
        {
            if (isDisposed)
                return;

            if (disposing)
            {
                if (_connection != null)
                {
                    _connection.Dispose();
                    _connection = null;
                }
            }

            isDisposed = true;
        }

        public void Dispose()
        {
            Dispose(true);
        }

        public int ExecuteNonQuery(string commandText, params SQLiteParameter[] parameters)
        {
            lock (_writeLock)
            {
                using (var command = new SQLiteCommand(commandText, _connection))
                {
                    foreach (var parameter in parameters)
                    {
                        command.Parameters.Add(parameter);
                    }
                    return command.ExecuteNonQuery();
                }
            }
        }

        public object ExecuteScalar(string commandText, params SQLiteParameter[] parameters)
        {
            using (var command = new SQLiteCommand(commandText, _connection))
            {
                foreach (var parameter in parameters)
                {
                    command.Parameters.Add(parameter);
                }
                return command.ExecuteScalar();
            }
        }

        public object WriteLock { get { return _writeLock; } }
    }
}
