stefanrenne/RxSonosLib

View on GitHub
RxSonosLib/Framework/Domain/Modal/Group.swift

Summary

Maintainability
B
5 hrs
Test Coverage
//
//  Group.swift
//  RxSonosLib
//
//  Created by Stefan Renne on 02/03/2018.
//  Copyright © 2018 Uberweb. All rights reserved.
//

import Foundation
import RxSwift

open class Group {
    
    /// The Master Room handles all requests that are fired to the Sonos Group
    public let master: Room
    
    /// Only some requests are also processed by slave rooms, as example volume controll requests
    public let slaves: [Room]
    
    /// Name of the group
    public lazy var name: String = {
        return (slaves.count > 0) ? "\(master.name) +\(slaves.count)" : master.name
    }()
    
    /// All Room names in this group
    public lazy var names: [String] = {
        return Array(Set(rooms.map({ $0.name })))
    }()
    
    /// All Rooms in this group
    internal var rooms: [Room] {
        return [master] + slaves
    }
    
    /// Active Track for this Group
    internal let activeTrack: BehaviorSubject<Track?> = BehaviorSubject(value: nil)
    internal let disposebag = DisposeBag()
    
    init(master: Room, slaves: [Room]) {
        self.master = master
        self.slaves = slaves
        observerActiveTrack()
    }
    
}

extension Group: Equatable {
    public static func == (lhs: Group, rhs: Group) -> Bool {
        
        return lhs.master == rhs.master && lhs.slaves.sorted(by: sortRooms) == rhs.slaves.sorted(by: sortRooms)
    }
}

private func sortRooms(room1: Room, room2: Room) -> Bool {
    return room1.uuid > room2.uuid
}

extension Group {
    private func observerActiveTrack() {
        SonosInteractor
            .getTrack(self)
            .subscribe(activeTrack)
            .disposed(by: disposebag)
    }
}

extension ObservableType where E == Group {
    public func getRooms() -> Observable<[Room]> {
        return
            self
            .map({ (group) -> [Room] in
                return group.rooms
            })
            .distinctUntilChanged()
    }
    
    public func getTrack() -> Observable<Track?> {
        return
            self
            .flatMap({ (group) -> Observable<Track?> in
                return group
                    .activeTrack
                    .asObserver()
            })
    }
    
    public func getImage() -> Observable<Data?> {
        return
            self
            .getTrack()
            .flatMap(ignoreNil)
            .flatMap({ (track) -> Observable<Data?> in
                return Observable
                    .just(track)
                    .getImage()
            })
            .distinctUntilChanged()
    }
    
    public func getProgress() -> Observable<GroupProgress> {
        return
            self
            .flatMap({ (group) -> Observable<GroupProgress> in
                return SonosInteractor.getProgress(group)
            })
            .distinctUntilChanged()
    }
    
    public func getQueue() -> Observable<[MusicProviderTrack]> {
        return
            self
            .flatMap({ (group) -> Observable<[MusicProviderTrack]> in
                return SonosInteractor.getQueue(group)
            })
    }
    
    public func getTransportState() -> Observable<TransportState> {
        return
            self
            .flatMap({ (group) -> Observable<TransportState> in
                return SonosInteractor.getTransportState(group)
            })
    }
    
    public func set(transportState: TransportState) -> Completable {
        return
            self
            .take(1)
            .asSingle()
            .flatMapCompletable({ (group) -> Completable in
                return SonosInteractor.setTransport(state: transportState, for: group)
            })
    }
    
    public func getVolume() -> Observable<Int> {
        return
            self
            .flatMap({ (group) -> Observable<Int> in
                return SonosInteractor.getVolume(group)
            })
    }
    
    public func set(volume: Int) -> Completable {
        return
            self
            .take(1)
            .asSingle()
            .flatMapCompletable({ (group) -> Completable in
                return SonosInteractor.set(volume: volume, for: group)
            })
    }
    
    public func setNextTrack() -> Completable {
        return
            self
            .take(1)
            .asSingle()
            .flatMapCompletable({ (group) -> Completable in
                return SonosInteractor.setNextTrack(group)
            })
    }
    
    public func setPreviousTrack() -> Completable {
        return
            self
            .take(1)
            .asSingle()
            .flatMapCompletable({ (group) -> Completable in
                return SonosInteractor.setPreviousTrack(group)
            })
    }
    
    public func getMute() -> Observable<[Bool]> {
        return
            self
            .take(1)
            .getRooms()
            .getMute()
    }
    
    public func set(mute enabled: Bool) -> Completable {
        return
            self
            .take(1)
            .getRooms()
            .set(mute: enabled)
    }
}