import Combine
import GRDB
import GRDBQuery

/// A player request can be used with the `@Query` property wrapper in order to
/// feed a view with a list of players.
///
/// For example:
///
///     struct MyView: View {
///         @Query(LineRequest(ordering: .byName)) private var players: [Line]
///
///         var body: some View {
///             List(players) { player in ... )
///         }
///     }

var bookColumn = Column("book")
struct LineRequest: Queryable {
    enum Ordering {
        case byScore
        case byName
    }

    /// The ordering used by the player request.
    var ordering: Ordering
    var book: String

    
    // MARK: - Queryable Implementation
    
    static var defaultValue: [Line] { [] }
    
    func publisher(in appDatabase: AppDatabase) -> AnyPublisher<[Line], Error> {
        // Build the publisher from the general-purpose read-only access
        // granted by `appDatabase.reader`.
        // Some apps will prefer to call a dedicated method of `appDatabase`.
        ValueObservation
            .tracking(fetchValue(_:))
            .publisher(
                in: appDatabase.reader,
                // The `.immediate` scheduling feeds the view right on
                // subscription, and avoids an undesired animation when the
                // application starts.
                scheduling: .immediate)
            .eraseToAnyPublisher()
    }
    
    // This method is not required by Queryable, but it makes it easier
    // to test LineRequest.
    func fetchValue(_ db: Database) throws -> [Line] {
        if book == "" {
            return try Line.filter(bookColumn ==  Line.randomBook()).fetchAll(db)
        } else {
            return try Line.filter(bookColumn ==  book).fetchAll(db)
        }
        // switch ordering {
        // case .byScore:
        //     return try Line.all().fetchAll(db)
        // case .byName:
        //     // return try Line.all().orderedByName().fetchAll(db)
        //     return try Line.all().fetchAll(db)
        // }
    }
}
