     
     // Metoda sprawdza czy odpowiedź serwera zawiera pole 'message' - jeśli tak oznacza to, że coś poszło nie tak,
     // w przypadku jego braku dostajemy dane o które prosiliśmy
-    private func wrongRequest(response rawJson: AnyObject) -> ServerResultType<JSON> {
+    private func wrongRequest(responseValue rawJson: AnyObject) -> ServerResultType<JSON> {
         let json = JSON(rawJson)
         if let message = json.dictionary?["message"]?.string {
-            return .WrongRequest(obj: message)
+            return .Error(err: ServerError.ErrorWithMessage(text: message))
         }
         return .Success(obj: json)
     }
     
     // Jeśli udało się zalogować metoda zwróci ServerResultType.Success z obiektem nil,
     // w przeciwnym wypadku obiekt to String z odpowiedzią serwera (powód błędu logowania)
-    public func login(username: String, password: String, completion: (ServerResultType<String?>)->()) {
+    public func login(username: String, password: String, completion: (ServerResultType<JSON>)->()) {
         request(.GET, url: url(fromRouter: Router.User(child: .Current))).responseJSON {
             
             switch $0.result {
             case .Success(let value):
                 
-                let json = JSON(value)
+                let wrongRequest = self.wrongRequest(responseValue: value)
                 
-                if let message = json.dictionary?["message"]?.string {
-                    completion(.WrongRequest(obj: message))
-                } else {
+                if case .Success = wrongRequest {
                     self.username = username
                     self.password = password
-                    self.defaults.setObject(username, forKey: UserData.Username.rawValue)
-                    self.defaults.setObject(password, forKey: UserData.Password.rawValue)
-                    
-                    completion(.Success(obj: nil))
+                    self.defaults.setObject(username, forKey: UserDefaultsKeys.LoggedUserUsername.rawValue)
+                    self.defaults.setObject(password, forKey: UserDefaultsKeys.LoggedUserPassword.rawValue)
                 }
+                completion(wrongRequest)
                 
             case .Failure(let error):
-                completion(.Error(error: error))
+                completion(.Error(err: error))
             }
         }
     }
     
     
     func deck(deckID: String?, completion: (ServerResultType<JSON>) -> ()) {
-        request(.GET, url: url(fromRouter: Router.Deck(child: .Get(id: deckID)))).responseJSON {
+        var router: Router!
+        if let deckID = deckID {
+            router = Router.Deck(child: .Single(id: deckID))
+        } else {
+            router = Router.Deck(child: .All)
+        }
+        request(.GET, url: url(fromRouter: router)).responseJSON {
             switch $0.result {
             case .Success(let value):
-                completion(self.wrongRequest(response: value))
+                completion(self.wrongRequest(responseValue: value))
             case .Failure(let error):
-                completion(.Error(error: error))
+                completion(.Error(err: error))
             }
             
         }

        return true
    }
    
    func get<T: Object>(withId idKey: String) -> T? {
        return realm?.objectForPrimaryKey(T.self, key: idKey)
    }
    
    func get<T: Object>(filter: String?) -> [T]? {
        return realm?.objects(T.self).toArray()
    }
    
    func update(object: Object) -> Bool {

struct ManagerMode: OptionSetType {
    var rawValue: Int
    
    static let Local = ManagerMode(rawValue: 1 << 0)
    static let Remote = ManagerMode(rawValue: 1 << 1)
    
}

public enum DataManagerResponseType {
    case Local, Remote
}

public enum DataManagerResponse<T> {
    case Success(obj: T, responseType: DataManagerResponseType)
    case Error(obj: NewDataManagerError, responseType: DataManagerResponseType)
}

public enum NewDataManagerError: ErrorType {
    case JSONParseError, ServerError(err: ErrorType), NoDeckWithGivenId, ErrorWithMessage(text: String), DataManagerWasDeinitialized
}
private class ModeHandler<T> {
    var local: (() -> DataManagerResponse<T>)?
    
    // wylaczenie ostrzezenia swift lint, aby moc przypisac wartosci poszczegolnym blokom bez ponownego pisania ich typu 
    // force unwrap zamiast optional, poniewaz w przypadku odwolania do serwera powinny zostac obsluzone oba przypadki
    var remote: (remoteSuccess: ((obj: JSON) -> DataManagerResponse<T>)!, //swiftlint:disable:this force_unwrapping
                remoteError: ((obj: ErrorType) -> DataManagerResponse<T>)!)?     //swiftlint:disable:this force_unwrapping

    var remoteRequest: (() -> ())?
    var activeMode: ManagerMode
    var callback: (DataManagerResponse<T>) -> ()
    
    init(withMode mode: ManagerMode, callback: (DataManagerResponse<T>) -> ()) {
        self.activeMode = mode
        self.callback = callback
    }
    
    func start() {
        if activeMode.contains(.Remote) {
            remoteRequest?()
        } else if activeMode == .Local {
            local?()
        }
    }
    
}
public class NewDataManager {
    
    let remoteDataManager = RemoteDataManager()
    let localDataManager = LocalDataManager()
    
    var mode: ManagerMode = [.Local, .Remote]
    
    private func handlerCompletion<T>(handler: ModeHandler<T>) -> (response: ServerResultType<JSON>) -> () {
    
        return { response in
            
            switch response {
            case .Success(let obj):
                if let result = handler.remote?.remoteSuccess(obj: obj) {
                    handler.callback(result)
                }
            case .Error(let obj):
                if handler.activeMode.contains(.Local), let local = handler.local {
                    handler.callback(local())
                } else if let result = handler.remote?.remoteError(obj: obj) {
                    handler.callback(result)
                }
                
            }
            handler.remoteRequest = nil
        }
    }
    
    func getDeck(withDeckId deckID: String, managerCompletion: (DataManagerResponse<Deck>)-> ()) {
       
        let modeBlocks = ModeHandler<Deck>(withMode: mode, callback: managerCompletion)
       
        modeBlocks.remoteRequest = {
            self.remoteDataManager.deck(deckID, completion: self.handlerCompletion(modeBlocks))
        }
        modeBlocks.local = {
            if let deck  = self.localDataManager.get(Deck.self, withId: deckID) {
                return .Success(obj: deck, responseType: .Local)
            } else {
                return .Error(obj: .NoDeckWithGivenId, responseType: .Local)
            }
        }
        
        modeBlocks.remote = (nil, nil)
        
        modeBlocks.remote?.remoteSuccess = {  obj in
            if let deck = Deck.withJSON(obj) {
                self.localDataManager.update(deck)
                return .Success(obj: deck, responseType: .Remote)
            } else {
                return .Error(obj: .JSONParseError, responseType: .Remote)
            }
            
        }
        
        modeBlocks.remote?.remoteError = { obj in
            return .Error(obj: .ServerError(err: obj), responseType: .Remote)
        }
        
        modeBlocks.start()
    }
}
