using Microsoft.Data.Sqlite;
using System;
using System.Drawing;
using System.IO;

namespace BookmarkManager
{
    public class IconDatabase
    {
        protected string dbFilename = null;
        protected SqliteConnection dbConnection = null;


        public IconDatabase(string filename)
        {
            if (string.IsNullOrWhiteSpace(filename)) return;

            dbFilename = filename;

            bool isNew = !File.Exists(dbFilename);

            SqliteConnectionStringBuilder builder = new SqliteConnectionStringBuilder();
            builder.DataSource = dbFilename;
            builder.Cache = SqliteCacheMode.Private;
            builder.Mode = SqliteOpenMode.ReadWriteCreate;

            dbConnection = new SqliteConnection(builder.ToString());
            dbConnection.Open();

            if (isNew) Initialise();

        }

        public bool AddIcon(string id, Image image)
        {
            if (dbConnection == null) return false;
            if (string.IsNullOrWhiteSpace(id)) return false;

            if (image == null) return DeleteIcon(id);
            if (HasIcon(id)) return UpdateIcon(id, image);

            SqliteCommand command = new SqliteCommand();
            command.Connection = dbConnection;
            command.CommandText = "INSERT INTO icons (id, content) VALUES (@id, @content)";
            command.Parameters.Add("@id", SqliteType.Text).Value = id;
            command.Parameters.Add("@content", SqliteType.Blob).Value = ImageToBytes(image);

            try
            {
                command.ExecuteNonQuery();
            }
            catch (Exception)
            {
                return false;
            }

            return true;
        }

        public void Close()
        {
            if (dbConnection == null) return;

            dbConnection.Close();
            dbConnection.Dispose();
            dbConnection = null;
        }

        public bool DeleteIcon(string id)
        {
            if (dbConnection == null) return false;
            if (string.IsNullOrWhiteSpace(id)) return false;

            SqliteCommand command = new SqliteCommand();
            command.Connection = dbConnection;
            command.CommandText = "DELETE FROM icons WHERE id = @id";
            command.Parameters.Add("@id", SqliteType.Text).Value = id;

            try
            {
                command.ExecuteNonQuery();
            }
            catch (Exception)
            {
                return false;
            }

            return true;
        }

        public Image FindIcon(string id)
        {
            if (dbConnection == null) return null;
            if (string.IsNullOrWhiteSpace(id)) return null;

            if (!HasIcon(id)) return null;

            byte[] iconBytes = null;

            SqliteCommand command = new SqliteCommand();
            command.Connection = dbConnection;
            command.CommandText = "SELECT content FROM icons WHERE id = @id";
            command.Parameters.Add("@id", SqliteType.Text).Value = id;

            try
            {
                var rs = command.ExecuteScalar();
                if (rs != null)
                {
                    iconBytes = (byte[])rs;
                }

                command.Dispose();
            }
            catch (Exception)
            {
                return null;
            }

            if (iconBytes == null)
            {
                return null;
            }

            Image img = null;

            try
            {
                img = Image.FromStream(new MemoryStream(iconBytes));
            }
            catch (Exception)
            {
                return null;
            }

            return img;
        }

        public bool HasIcon(string id)
        {
            if (dbConnection == null) return false;
            if (string.IsNullOrWhiteSpace(id)) return false;

            string rs = string.Empty;

            SqliteCommand command = new SqliteCommand();
            command.Connection = dbConnection;
            command.CommandText = "SELECT COUNT(1) AS count FROM icons WHERE id = @id";
            command.Parameters.Add("@id", SqliteType.Text).Value = id;

            try
            {
                rs = command.ExecuteScalar()?.ToString() ?? string.Empty;

                command.Dispose();
            }
            catch (Exception)
            {
                return false;
            }

            int rv;
            if (!int.TryParse(rs, out rv)) rv = 0;

            return (rv > 0);
        }

        public bool UpdateIcon(string id, Image image)
        {
            if (dbConnection == null) return false;
            if (string.IsNullOrWhiteSpace(id)) return false;

            if (image == null) return DeleteIcon(id);
            if (!HasIcon(id)) return AddIcon(id, image);

            SqliteCommand command = new SqliteCommand();
            command.Connection = dbConnection;
            command.CommandText = "UPDATE icons SET content = @content WHERE id = @id";
            command.Parameters.Add("@id", SqliteType.Text).Value = id;
            command.Parameters.Add("@content", SqliteType.Blob).Value = ImageToBytes(image);

            try
            {
                command.ExecuteNonQuery();
            }
            catch (Exception)
            {
                return false;
            }

            return true;
        }


        protected bool Initialise()
        {
            if (dbConnection == null) return false;

            try
            {
                SqliteCommand command = new SqliteCommand("CREATE TABLE icons (id TEXT PRIMARY KEY, content BLOB)", dbConnection);
                command.ExecuteNonQuery();
                command.Dispose();
            }
            catch (Exception)
            {
                return false;
            }

            return true;
        }

        protected byte[] ImageToBytes(Image image)
        {
            ImageConverter imageConverter = new ImageConverter();
            return (byte[])imageConverter.ConvertTo(image, typeof(byte[]));
        }

    }
}