//
//  Array+Uniques.swift
//  Tusker
//
//  Created by Shadowfacts on 1/6/19.
//  Copyright © 2019 Shadowfacts. All rights reserved.
//

import Foundation

extension Array {
    func uniques<ID: Hashable>(by identify: (Element) -> ID) -> [Element] {
        var uniques = Set<Hashed<Element, ID>>()
        for (index, elem) in self.enumerated() {
            uniques.insert(Hashed(element: elem, id: identify(elem), origIndex: index))
        }
        return uniques.sorted(by: { $0.origIndex < $1.origIndex }).map(\.element)
    }
}

extension Array where Element: Hashable {
    func uniques() -> [Element] {
        return uniques(by: { $0 })
    }
}

fileprivate struct Hashed<Element, ID: Hashable>: Hashable {
    let element: Element
    let id: ID
    let origIndex: Int
    
    static func ==(lhs: Self, rhs: Self) -> Bool {
        return lhs.id == rhs.id
    }
    
    func hash(into hasher: inout Hasher) {
        hasher.combine(id)
    }
}
