// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import "dart:collection";
import "dart:ffi";

import "package:ffi/ffi.dart";

import "bindings/bindings.dart";

import "bindings/types.dart" as types;
import "bindings/types.dart" hide Database;

import "bindings/constants.dart";
import "collections/closable_iterator.dart";

/// [Database] represents an open connection to a SQLite database.
///
/// All functions against a database may throw [SQLiteError].
///
/// This database interacts with SQLite synchronously.
class Database {
  late DatabaseResource _database;
  bool _open = false;

  /// Open a database located at the file [path].
  Database(String path,
      [int flags = Flags.SQLITE_OPEN_READWRITE | Flags.SQLITE_OPEN_CREATE]) {
    Pointer<Pointer<types.Database>> dbOut = calloc();
    final pathC = Utf8Resource(path.toNativeUtf8());
    final int resultCode =
        bindings.sqlite3_open_v2(pathC.unsafe(), dbOut, flags, nullptr);
    _database = DatabaseResource(dbOut.value);
    calloc.free(dbOut);
    pathC.free();

    if (resultCode == Errors.SQLITE_OK) {
      _open = true;
    } else {
      // Even if "open" fails, sqlite3 will still create a database object. We
      // can just destroy it.
      SQLiteException exception = _loadError(resultCode);
      close();
      throw exception;
    }
  }

  /// Close the database.
  ///
  /// This should only be called once on a database unless an exception is
  /// thrown. It should be called at least once to finalize the database and
  /// avoid resource leaks.
  void close() {
    assert(_open);
    final int resultCode = _database.close();
    if (resultCode == Errors.SQLITE_OK) {
      _open = false;
    } else {
      throw _loadError(resultCode);
    }
  }

  /// Execute a query, discarding any returned rows.
  void execute(String query) {
    Pointer<Pointer<Statement>> statementOut = malloc();
    final queryC = Utf8Resource(query.toNativeUtf8());
    int resultCode = _database.prepare(queryC, -1, statementOut, nullptr);
    final statement = StatementResource(statementOut.value);
    calloc.free(statementOut);
    queryC.free();

    while (resultCode == Errors.SQLITE_ROW || resultCode == Errors.SQLITE_OK) {
      resultCode = statement.step();
    }
    statement.finalize();
    if (resultCode != Errors.SQLITE_DONE) {
      throw _loadError(resultCode);
    }
  }

  /// Evaluate a query and return the resulting rows as an iterable.
  Result query(String query) {
    Pointer<Pointer<Statement>> statementOut = malloc();
    final queryC = Utf8Resource(query.toNativeUtf8());
    int resultCode = _database.prepare(queryC, -1, statementOut, nullptr);
    final statement = StatementResource(statementOut.value);
    calloc.free(statementOut);
    queryC.free();

    if (resultCode != Errors.SQLITE_OK) {
      statement.finalize();
      throw _loadError(resultCode);
    }

    Map<String, int> columnIndices = {};
    int columnCount = statement.columnCount;
    for (int i = 0; i < columnCount; i++) {
      String columnName = statement.columnName(i);
      columnIndices[columnName] = i;
    }

    return Result._(this, statement, columnIndices);
  }

  SQLiteException _loadError([int? errorCode]) {
    String errorMessage = _database.errmsg().toDartString();
    if (errorCode == null) {
      return SQLiteException(errorMessage);
    }
    String errorCodeExplanation =
        bindings.sqlite3_errstr(errorCode).toDartString();
    return SQLiteException(
        "$errorMessage (Code $errorCode: $errorCodeExplanation)");
  }
}

/// [Result] represents a [Database.query]'s result and provides an [Iterable]
/// interface for the results to be consumed.
///
/// Please note that this iterator should be [close]d manually if not all [Row]s
/// are consumed.
class Result extends IterableBase<Row> implements ClosableIterable<Row> {
  final ClosableIterator<Row> _iterator;

  Result._(
    Database database,
    StatementResource statement,
    Map<String, int> columnIndices,
  ) : _iterator = _ResultIterator(statement, columnIndices) {}

  void close() => _iterator.close();

  ClosableIterator<Row> get iterator => _iterator;
}

class _ResultIterator implements ClosableIterator<Row> {
  final StatementResource _statement;
  final Map<String, int> _columnIndices;

  Row? _currentRow;
  bool _closed = false;

  _ResultIterator(this._statement, this._columnIndices) {}

  bool moveNext() {
    if (_closed) {
      throw SQLiteException("The result has already been closed.");
    }
    _currentRow?._setNotCurrent();
    int stepResult = _statement.step();
    if (stepResult == Errors.SQLITE_ROW) {
      _currentRow = Row._(_statement, _columnIndices);
      return true;
    } else {
      close();
      return false;
    }
  }

  Row get current {
    if (_closed) {
      throw SQLiteException("The result has already been closed.");
    }
    return _currentRow!;
  }

  void close() {
    _currentRow?._setNotCurrent();
    _closed = true;
    _statement.finalize();
  }
}

class Row {
  final StatementResource _statement;
  final Map<String, int> _columnIndices;

  bool _isCurrentRow = true;

  Row._(this._statement, this._columnIndices) {}

  /// Reads column [columnName].
  ///
  /// By default it returns a dynamically typed value. If [convert] is set to
  /// [Convert.StaticType] the value is converted to the static type computed
  /// for the column by the query compiler.
  dynamic readColumn(String columnName,
      {Convert convert = Convert.DynamicType}) {
    return readColumnByIndex(_columnIndices[columnName]!, convert: convert);
  }

  /// Reads column [columnName].
  ///
  /// By default it returns a dynamically typed value. If [convert] is set to
  /// [Convert.StaticType] the value is converted to the static type computed
  /// for the column by the query compiler.
  dynamic readColumnByIndex(int columnIndex,
      {Convert convert = Convert.DynamicType}) {
    _checkIsCurrentRow();

    Type dynamicType;
    if (convert == Convert.DynamicType) {
      dynamicType = _typeFromCode(_statement.columnType(columnIndex));
    } else {
      dynamicType =
          _typeFromText(_statement.columnDecltype(columnIndex).toDartString());
    }

    switch (dynamicType) {
      case Type.Integer:
        return readColumnByIndexAsInt(columnIndex);
      case Type.Text:
        return readColumnByIndexAsText(columnIndex);
      case Type.Null:
        return null;
      default:
    }
  }

  /// Reads column [columnName] and converts to [Type.Integer] if not an
  /// integer.
  int readColumnAsInt(String columnName) {
    return readColumnByIndexAsInt(_columnIndices[columnName]!);
  }

  /// Reads column [columnIndex] and converts to [Type.Integer] if not an
  /// integer.
  int readColumnByIndexAsInt(int columnIndex) {
    _checkIsCurrentRow();
    return _statement.columnInt(columnIndex);
  }

  /// Reads column [columnName] and converts to [Type.Text] if not text.
  String readColumnAsText(String columnName) {
    return readColumnByIndexAsText(_columnIndices[columnName]!);
  }

  /// Reads column [columnIndex] and converts to [Type.Text] if not text.
  String readColumnByIndexAsText(int columnIndex) {
    _checkIsCurrentRow();
    return _statement.columnText(columnIndex).toDartString();
  }

  void _checkIsCurrentRow() {
    if (!_isCurrentRow) {
      throw Exception(
          "This row is not the current row, reading data from the non-current"
          " row is not supported by sqlite.");
    }
  }

  void _setNotCurrent() {
    _isCurrentRow = false;
  }
}

class DatabaseResource implements Finalizable {
  static final NativeFinalizer _finalizer =
      NativeFinalizer(bindings.sqlite3_close_v2_native_return_void.cast());

  /// [_statement] must never escape [StatementResource], otherwise the
  /// [_finalizer] will run prematurely.
  Pointer<types.Database> _database;

  DatabaseResource(this._database) {
    _finalizer.attach(this, _database.cast(), detach: this);
  }

  int close() {
    _finalizer.detach(this);
    return bindings.sqlite3_close_v2(_database);
  }

  int prepare(Utf8Resource query, int nbytes,
      Pointer<Pointer<Statement>> statementOut, Pointer<Pointer<Utf8>> tail) {
    int result = bindings.sqlite3_prepare_v2(
        _database, query.unsafe(), nbytes, statementOut, tail);
    return result;
  }

  Pointer<Utf8> errmsg() => bindings.sqlite3_errmsg(_database);
}

class StatementResource implements Finalizable {
  static final NativeFinalizer _finalizer =
      NativeFinalizer(bindings.sqlite3_finalize_native_return_void.cast());

  /// [_statement] must never escape [StatementResource], otherwise the
  /// [_finalizer] will run prematurely.
  final Pointer<Statement> _statement;

  StatementResource(this._statement) {
    _finalizer.attach(this, _statement.cast(), detach: this);
  }

  int finalize() {
    _finalizer.detach(this);
    return bindings.sqlite3_finalize(_statement);
  }

  int get columnCount => bindings.sqlite3_column_count(_statement);

  String columnName(int index) =>
      bindings.sqlite3_column_name(_statement, index).toDartString();

  int step() => bindings.sqlite3_step(_statement);

  int columnType(int columnIndex) =>
      bindings.sqlite3_column_type(_statement, columnIndex);

  Pointer<Utf8> columnDecltype(int columnIndex) =>
      bindings.sqlite3_column_decltype(_statement, columnIndex);

  int columnInt(int columnIndex) =>
      bindings.sqlite3_column_int(_statement, columnIndex);

  Pointer<Utf8> columnText(int columnIndex) =>
      bindings.sqlite3_column_text(_statement, columnIndex);
}

class Utf8Resource implements Finalizable {
  static final NativeFinalizer _finalizer = NativeFinalizer(posixFree);

  /// [_cString] must never escape [Utf8Resource], otherwise the
  /// [_finalizer] will run prematurely.
  final Pointer<Utf8> _cString;

  Utf8Resource(this._cString) {
    _finalizer.attach(this, _cString.cast(), detach: this);
  }

  void free() {
    _finalizer.detach(this);
    calloc.free(_cString);
  }

  /// Ensure this [Utf8Resource] stays in scope longer than the inner resource.
  Pointer<Utf8> unsafe() => _cString;
}

final DynamicLibrary stdlib = DynamicLibrary.process();
final posixFree = stdlib.lookup<NativeFunction<Void Function(Pointer)>>("free");

Type _typeFromCode(int code) {
  switch (code) {
    case Types.SQLITE_INTEGER:
      return Type.Integer;
    case Types.SQLITE_FLOAT:
      return Type.Float;
    case Types.SQLITE_TEXT:
      return Type.Text;
    case Types.SQLITE_BLOB:
      return Type.Blob;
    case Types.SQLITE_NULL:
      return Type.Null;
  }
  throw Exception("Unknown type [$code]");
}

Type _typeFromText(String textRepresentation) {
  switch (textRepresentation) {
    case "integer":
      return Type.Integer;
    case "float":
      return Type.Float;
    case "text":
      return Type.Text;
    case "blob":
      return Type.Blob;
    case "null":
      return Type.Null;
  }
  throw Exception("Unknown type [$textRepresentation]");
}

enum Type { Integer, Float, Text, Blob, Null }

enum Convert { DynamicType, StaticType }

class SQLiteException {
  final String message;
  SQLiteException(this.message);

  String toString() => message;
}
