// 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;
}
