//
//  Pagination.swift
//  Pachyderm
//
//  Created by Shadowfacts on 9/9/18.
//  Copyright © 2018 Shadowfacts. All rights reserved.
//

import Foundation

public struct Pagination: Sendable {
    public let older: RequestRange?
    public let newer: RequestRange?
}

extension Pagination {
    init(string: String) {
        let links = string.components(separatedBy: ",").compactMap(Item.init)
        self.older = links.first(where: { $0.kind == .next })?.range
        self.newer = links.first(where: { $0.kind == .prev })?.range
    }
}

extension Pagination {
    struct Item {
        let kind: Kind
        let id: String
        let limit: Int?
        
        var range: RequestRange {
            switch kind {
            case .next:
                return .before(id: id, count: limit)
            case .prev:
                return .after(id: id, count: limit)
            }
        }
        
        init?(string: String) {
            let segments = string.components(separatedBy: .whitespaces).filter { !$0.isEmpty }.joined().components(separatedBy: ";")
            
            let url = segments.first.flatMap { str in
                String(str[str.index(after: str.startIndex)..<str.index(before: str.endIndex)])
            }
            let rel = segments.last?.replacingOccurrences(of: "\"", with: "").trimmingCharacters(in: .whitespaces).components(separatedBy: "=")
            
            guard let validURL = url,
                let key = rel?.first,
                key == "rel",
                let value = rel?.last,
                let kind = Kind(rawValue: value),
                let components = URLComponents(string: validURL),
                let queryItems = components.queryItems else { return nil }
            
            let min = queryItems.first { $0.name == "min_id" }?.value
            let since = queryItems.first { $0.name == "since_id" }?.value
            let max = queryItems.first { $0.name == "max_id" }?.value
            
            guard let id = min ?? since ?? max else { return nil }
            
            let limit = queryItems.first { $0.name == "limit" }.flatMap { $0.value }.flatMap { Int($0) }
            
            self.kind = kind
            self.id = id
            self.limit = limit
        }
    }
}

extension Pagination.Item {
    enum Kind: String {
        case next, prev
    }
}
