//
//  SemiCaseSensitiveComparator.swift
//  Tusker
//
//  Created by Shadowfacts on 11/30/22.
//  Copyright © 2022 Shadowfacts. All rights reserved.
//

import Foundation

/// A comparator that sorts objects with a string key path case insensitively unless they're the same, in which case uppercase comes after lowercase.
struct SemiCaseSensitiveComparator: SortComparator {
    var order: SortOrder = .forward
    
    typealias Compared = String
    
    static func keyPath<Object>(_ keyPath: KeyPath<Object, String>) -> KeyPathComparator<Object> {
        return KeyPathComparator(keyPath, comparator: SemiCaseSensitiveComparator())
    }
    
    func compare(_ lhs: String, _ rhs: String) -> ComparisonResult {
        let result = doCompare(lhs, rhs)
        if case .reverse = order {
            switch result {
            case .orderedDescending:
                return .orderedAscending
            case .orderedAscending:
                return .orderedDescending
            case .orderedSame:
                return .orderedSame
            }
        } else {
            return result
        }
    }
    
    private func doCompare(_ lhs: String, _ rhs: String) -> ComparisonResult {
        for (l, r) in zip(lhs, rhs) {
            let lLower = l.lowercased()
            let rLower = r.lowercased()
            if lLower < rLower {
                return .orderedAscending
            } else if lLower > rLower {
                return .orderedDescending
            } else {
                if l < r {
                    return .orderedDescending
                } else if l > r {
                    return .orderedAscending
                }
            }
        }
        if lhs.count > rhs.count {
            return .orderedDescending
        } else if lhs.count < rhs.count {
            return .orderedAscending
        } else {
            return .orderedSame
        }
    }
}
