/*
 * Copyright 2016 Andrey Tolpeev
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.github.vase4kin.teamcityapp.favorites.interactor;

import android.support.annotation.NonNull;

import com.github.vase4kin.teamcityapp.account.create.data.OnLoadingListener;
import com.github.vase4kin.teamcityapp.api.Repository;
import com.github.vase4kin.teamcityapp.api.interfaces.Collectible;
import com.github.vase4kin.teamcityapp.base.list.data.BaseListRxDataManagerImpl;
import com.github.vase4kin.teamcityapp.navigation.api.BuildType;
import com.github.vase4kin.teamcityapp.navigation.api.NavigationItem;
import com.github.vase4kin.teamcityapp.storage.SharedUserStorage;

import java.util.List;

import rx.Observable;
import rx.functions.Func1;
import rx.functions.Func2;

/**
 * Impl of {@link FavoritesInteractor}
 */
public class FavoritesInteractorImpl extends BaseListRxDataManagerImpl<FavoritesInteractorImpl.NavigationItemsList, NavigationItem> implements FavoritesInteractor {

    private final Repository repository;
    private final SharedUserStorage storage;

    public FavoritesInteractorImpl(Repository repository, SharedUserStorage storage) {
        this.repository = repository;
        this.storage = storage;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void loadFavorites(@NonNull OnLoadingListener<List<NavigationItem>> loadingListener, final boolean update) {
        List<String> ids = storage.getFavoriteBuildTypeIds();
        Observable<NavigationItemsList> favoritesObservable = Observable.from(ids)
                .flatMap(new Func1<String, Observable<NavigationItem>>() {
                    @Override
                    public Observable<NavigationItem> call(String id) {
                        return repository.buildType(id, update)
                                .onErrorResumeNext(new Func1<Throwable, Observable<? extends BuildType>>() {
                                    @Override
                                    public Observable<? extends BuildType> call(Throwable throwable) {
                                        return Observable.empty();
                                    }
                                })
                                .flatMap(new Func1<BuildType, Observable<NavigationItem>>() {
                                    @Override
                                    public Observable<NavigationItem> call(BuildType buildType) {
                                        return Observable.just((NavigationItem) buildType);
                                    }
                                });
                    }
                })
                .toSortedList(new Func2<NavigationItem, NavigationItem, Integer>() {
                    @Override
                    public Integer call(NavigationItem navigationItem, NavigationItem navigationItem2) {
                        // sort by build type ids
                        return navigationItem.getId().compareToIgnoreCase(navigationItem2.getId());
                    }
                })
                .flatMap(new Func1<List<NavigationItem>, Observable<NavigationItemsList>>() {
                    @Override
                    public Observable<NavigationItemsList> call(List<NavigationItem> navigationItems) {
                        return Observable.just(new NavigationItemsList(navigationItems));
                    }
                });
        load(favoritesObservable, loadingListener);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int getFavoritesCount() {
        return storage.getFavoriteBuildTypeIds().size();
    }

    static class NavigationItemsList implements Collectible<NavigationItem> {

        private final List<NavigationItem> items;

        NavigationItemsList(List<NavigationItem> items) {
            this.items = items;
        }

        @Override
        public List<NavigationItem> getObjects() {
            return items;
        }
    }
}

@@ -2116,38 +2116,33 @@
  Observable%3C
-NavigationItem
+BuildType
 %3E%3E() %7B%0A     
@@ -2200,38 +2200,33 @@
  Observable%3C
-NavigationItem
+BuildType
 %3E call(Strin
@@ -2768,30 +2768,25 @@
 ervable%3C
-NavigationItem
+BuildType
 %3E%3E() %7B%0A 
@@ -2884,30 +2884,25 @@
 ervable%3C
-NavigationItem
+BuildType
 %3E call(B
@@ -2990,25 +2990,8 @@
 ust(
-(NavigationItem) 
 buil
@@ -3157,38 +3157,28 @@
 nc2%3C
-NavigationItem, NavigationItem
+BuildType, BuildType
 , In
@@ -3262,68 +3262,49 @@
 all(
-NavigationItem navigationItem, NavigationItem navigationItem
+BuildType buildType1, BuildType buildType
 2) %7B
@@ -3343,18 +3343,15 @@
  by 
-build type
+project
  ids
@@ -3386,25 +3386,28 @@
 urn 
-navigationItem.ge
+buildType1.getProjec
 tId(
@@ -3432,31 +3432,387 @@
 ase(
-navigationItem2.getId()
+(buildType2.getProjectId()));%0A                    %7D%0A                %7D)%0A                .flatMap(new Func1%3CList%3CBuildType%3E, Observable%3CList%3CNavigationItem%3E%3E%3E() %7B%0A                    @Override%0A                    public Observable%3CList%3CNavigationItem%3E%3E call(List%3CBuildType%3E buildTypes) %7B%0A                        return Observable.from(buildTypes).cast(NavigationItem.class).toList(
 );%0A 

Fix favorites sorting