package com.tobi.movies;

import com.tobi.movies.backend.Backend;
import com.tobi.movies.popularstream.ApiMoviePoster;
import com.tobi.movies.popularstream.ApiMoviePosterConverter;
import com.tobi.movies.popularstream.MoviePoster;
import com.tobi.movies.popularstream.PopularStreamApiDatasource;
import com.tobi.movies.popularstream.PopularStreamRepository;
import com.tobi.movies.posterdetails.ApiMovieDetails;
import com.tobi.movies.posterdetails.ApiMovieDetailsConverter;
import com.tobi.movies.posterdetails.MovieDetails;
import com.tobi.movies.posterdetails.MovieDetailsApiDatasource;
import com.tobi.movies.posterdetails.MovieDetailsRepository;

import rx.Scheduler;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

public class ApplicationDependencies implements Dependencies {

    private ImageLoader imageLoader;
    private Backend backend;
    private PopularStreamRepository streamRepository;
    private MovieDetailsRepository movieDetailsRepository;

    @Override
    public ImageLoader imageLoader() {
        if (imageLoader == null) {
            imageLoader = createImageLoader();
        }

        return imageLoader;
    }

    @Override
    public PopularStreamRepository streamRepository() {
        if (streamRepository == null) {
            streamRepository = createStreamRepository();
        }

        return streamRepository;
    }

    @Override
    public MovieDetailsRepository movieDetailsRepository() {
        if (movieDetailsRepository == null) {
            movieDetailsRepository = createMovieDetailsRepository();
        }
        return movieDetailsRepository;
    }

    @Override
    public Scheduler createSubscriberThread() {
        return Schedulers.io();
    }

    @Override
    public Scheduler createObserverThread() {
        return AndroidSchedulers.mainThread();
    }

    protected MovieDetailsRepository createMovieDetailsRepository() {
        return new MovieDetailsRepository(
                createMovieDetailsApiSource(),
                createMovieDetailsConverter()
        );
    }

    protected ImageLoader createImageLoader() {
        return new ImageLoader();
    }

    protected Converter<ApiMoviePoster, MoviePoster> createPosterConverter() {
        return new ApiMoviePosterConverter();
    }

    protected PopularStreamApiDatasource createStreamApiDataSource() {
        return new PopularStreamApiDatasource(backend());
    }

    @Deprecated
    protected Backend createBackend() {
        throw new IllegalStateException("Backend should be provided from BackendModule");
    }

    private PopularStreamRepository createStreamRepository() {
        return new PopularStreamRepository(
                createStreamApiDataSource(),
                createSubscriberThread(),
                createObserverThread(),
                createPosterConverter()
        );
    }

    protected Converter<ApiMovieDetails, MovieDetails> createMovieDetailsConverter() {
        return new ApiMovieDetailsConverter();
    }

    protected MovieDetailsApiDatasource createMovieDetailsApiSource() {
        return new MovieDetailsApiDatasource(backend());
    }

    protected Backend backend() {
        if (backend == null) {
            backend = createBackend();
        }

        return backend;
    }

    @Override
    public void setBackend(Backend backend) {
        this.backend = backend;
    }
}

@@ -2437,161 +2437,8 @@
  %7D%0A%0A
-    @Deprecated%0A    protected Backend createBackend() %7B%0A        throw new IllegalStateException(%22Backend should be provided from BackendModule%22);%0A    %7D%0A%0A
     
@@ -3083,32 +3083,79 @@
     
-backend = createBackend(
+throw new IllegalStateException(%22Backend should be provided via dagger%22
 );%0A 

Remove createBackend method from custom dependency injection since it's provided from dagger for production and tests