package com.mat_brandao.saudeapp.view.emergency;

import android.Manifest;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.net.Uri;
import android.os.Handler;
import android.support.design.widget.BottomSheetBehavior;
import android.support.design.widget.BottomSheetDialog;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.widget.NestedScrollView;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MapStyleOptions;
import com.google.android.gms.maps.model.Marker;
import com.google.gson.Gson;
import com.iarcuschin.simpleratingbar.SimpleRatingBar;
import com.mat_brandao.saudeapp.R;
import com.mat_brandao.saudeapp.domain.model.Conteudo;
import com.mat_brandao.saudeapp.domain.model.Error401;
import com.mat_brandao.saudeapp.domain.model.Establishment;
import com.mat_brandao.saudeapp.domain.util.GenericUtil;
import com.mat_brandao.saudeapp.domain.util.OnLocationFound;
import com.mat_brandao.saudeapp.domain.util.StringListener;
import com.mat_brandao.saudeapp.view.group.GroupActivity;
import com.mat_brandao.saudeapp.view.main.MainActivity;
import com.tbruyelle.rxpermissions.RxPermissions;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import butterknife.Bind;
import butterknife.ButterKnife;
import retrofit2.Response;
import rx.Observable;
import rx.Observer;
import rx.android.schedulers.AndroidSchedulers;
import rx.subscriptions.CompositeSubscription;

import static com.google.android.gms.internal.zzs.TAG;
import static com.mat_brandao.saudeapp.view.establishment.EstablishmentPresenterImpl.ESTABLISHMENT_INTENT_KEY;

public class EmergencyPresenterImpl implements EmergencyPresenter, OnLocationFound, OnMapReadyCallback, StringListener {

    private static final long DEBOUNCE_TIMER = 500;
    private static final float DEFAULT_ZOOM = 14f;
    private static final int ESTABLISHMENT_SEARCH_LIMIT = 30;

    private EmergencyInteractorImpl mInteractor;
    private Activity mContext;
    private EmergencyView mView;

    private Handler mHandler = new Handler();
    private Runnable mDismissKeyboardRunnable = () -> mView.dismissKeyboard();

    private List<Establishment> mEstablishmentList = new ArrayList<>();
    private List<Establishment> mRemoveList = new ArrayList<>();

    private CompositeSubscription mSubscription = new CompositeSubscription();

    private Observable<Response<List<Establishment>>> mLastObservable;
    private Observer<Response<List<Establishment>>> mLastObserver;
    private GoogleMap mMap;
    private Marker lastOpenned;
    private Location mLocation;

    private ProgressBar mEstablishmentProgress;
    private SimpleRatingBar mRatingView;
    private boolean isLiked;
    private List<String> mUfList;
    private ArrayAdapter mAdapter;
    private String mSearchText;
    private String mSearchUf;

    @Override
    public void onResume() {
        ((MainActivity) mContext).setNavigationItemChecked(R.id.menu_item_emergency);
    }

    @Override
    public void onPause() {

    }

    @Override
    public void onDestroy() {
        mSubscription.unsubscribe();
        mView = null;
    }

    @Override
    public void onRetryClicked() {
        mView.toggleFabButton(false);
        mView.setProgressFabVisibility(View.VISIBLE);
        mLastObservable
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(mLastObserver);
    }

    public EmergencyPresenterImpl(EmergencyView view, Activity context) {
        mInteractor = new EmergencyInteractorImpl(context);
        mContext = context;
        mView = view;

        setSpinnerAdapter();
        setupSearchObservable();
        requestLikedEstablishments();
    }

    private void setSpinnerAdapter() {
        mUfList = mInteractor.getUfList();
        mAdapter = new ArrayAdapter<>(mContext, android.R.layout.simple_spinner_item, mUfList);
        mView.setUfSpinnerAdapter(mAdapter);
    }

    private void setupSearchObservable() {
        mView.registerSearchEditTextObserver()
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(charSequence -> {
                    mHandler.removeCallbacks(mDismissKeyboardRunnable);
                });

        Observable<CharSequence> searchTextObservable = mView.registerSearchEditTextObserver();
        Observable<Integer> ufSpinnerObservable = mView.registerUfSpinnerObserver();

        searchTextObservable.subscribe();
        searchTextObservable.subscribe();

        Observable.combineLatest(searchTextObservable, ufSpinnerObservable,
                (charSequence, integer) -> {
                    mSearchText = charSequence.toString();
                    mSearchUf = mUfList.get(integer);
                    return (mSearchText.trim().length() > 3);
                }).debounce(500, TimeUnit.MILLISECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .skip(1)
                .subscribe(shouldFetch -> {
                    if (shouldFetch) {
                        try {
                            mEstablishmentList.clear();
                        } catch (Exception e) {
                        }
                        try {
                            mRemoveList.clear();
                        } catch (Exception e) {
                        }
                        mInteractor.clearMarkers(mMap);
                        mView.setProgressFabVisibility(View.VISIBLE);
                        mLastObservable = mInteractor.requestEstablishmentsByName(mSearchText, mSearchUf);
                        mLastObserver = requestEstablishmentsObserver;
                        mSubscription.add(mInteractor.requestEstablishmentsByName(mSearchText, mSearchUf)
                                .observeOn(AndroidSchedulers.mainThread())
                                .subscribe(requestEstablishmentsObserver));
                    } else {
                        mInteractor.clearMarkers(mMap);
                        mEstablishmentList.clear();
                        mEstablishmentList.addAll(mFilteredEstablishmentList);
                        showMapPins(mEstablishmentList);
                        try {
                            mInteractor.animateCameraToAllEstablishments(mMap);
                        } catch (IllegalStateException e) {
                        }
                    }
                });
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;
        MapStyleOptions style = MapStyleOptions.loadRawResourceStyle(mContext, R.raw.map_style);
        mMap.setMapStyle(style);
        checkPermissions();
        configureMapClickListener();
    }

    private void checkPermissions() {
        RxPermissions.getInstance(mContext)
                .request(Manifest.permission.ACCESS_COARSE_LOCATION,
                        Manifest.permission.ACCESS_FINE_LOCATION)
                .subscribe(granted -> {
                    if (granted) {
                        requestUserLocation();
                    } else {
                        mView.showToast(mContext.getString(R.string.needed_location_permission));
                        onNoGpsLayout();
                    }
                });
    }

    private void requestUserLocation() {
        if (mInteractor.hasGps()) {
            if (mInteractor.isGpsOn()) {
                onGpsLayout();
            } else {
                mView.showGpsDialog((dialogInterface, i) -> {
                    mView.startGpsIntent();
                });
            }
        } else {
            onNoGpsLayout();
        }
    }

    private void onGpsLayout() {
        mInteractor.requestMyLocation(this);
    }

    private void onNoGpsLayout() {
        mView.setProgressFabVisibility(View.GONE);
    }

    @Override
    public void onGpsTurnedOn() {
        onGpsLayout();
    }

    @Override
    public void onGpsTurnedOff() {
        onNoGpsLayout();
    }

    @Override
    public void onFilterFabClick() {
        showEmergencyBottomSheetDialog();
    }

    private void configureMapClickListener() {
        mMap.setOnMarkerClickListener(
                marker -> {
                    if (lastOpenned != null) {
                        lastOpenned.hideInfoWindow();
                        if (lastOpenned.equals(marker)) {
                            lastOpenned = null;
                            return true;
                        }
                    }

                    mInteractor.animateCameraToMarker(mMap, marker);
                    Establishment establishment = mInteractor.getEstablishmentFromMarker(marker);
                    if (establishment != null) {
                        new Handler().postDelayed(() -> {
                            mContext.runOnUiThread(() -> {
                                showEstablishmentBottomDialog(establishment);
                                getEstablishmentRating(Long.valueOf(establishment.getCodUnidade()));
                            });
                        }, 500);
                    }
                    marker.showInfoWindow();
                    lastOpenned = marker;
                    return true;
                });
    }

    private void requestLikedEstablishments() {
        mSubscription.add(mInteractor.requestGetUserLikePosts()
                .observeOn(AndroidSchedulers.mainThread())
                .onErrorReturn(throwable -> null)
                .subscribe(listResponse -> {
                    if (listResponse != null && listResponse.isSuccessful()) {
                        if (listResponse.body() != null && listResponse.body().size() > 0) {
                            mInteractor.saveUserLikePostCode(listResponse.body().get(0).getCodPostagem());
                            for (Conteudo conteudo : listResponse.body().get(0).getConteudos()) {
                                mInteractor.requestGetPostContent(conteudo.getCodConteudoPostagem())
                                        .observeOn(AndroidSchedulers.mainThread())
                                        .onErrorReturn(throwable -> null)
                                        .subscribe(postContentResponse -> {
                                            if (postContentResponse != null && postContentResponse.isSuccessful()) {
                                                mInteractor.addEstablishmentToLikedList(postContentResponse.body().getCodConteudoPost(),
                                                        GenericUtil.getNumbersFromString(postContentResponse.body().getJSON()));
                                            }
                                        });
                            }
                        } else {
                            mSubscription.add(mInteractor.requestCreateLikePost()
                                    .observeOn(AndroidSchedulers.mainThread())
                                    .onErrorReturn(throwable -> null)
                                    .subscribe(createPostResponse -> {
                                        if (createPostResponse != null && createPostResponse.isSuccessful()) {
                                            mInteractor.saveUserLikePostCode(GenericUtil.getNumbersFromString(createPostResponse.headers().get("location")));
                                        }
                                    }));
                        }
                    }
                }));
    }

    private void getEstablishmentRating(Long codUnidade) {
        mSubscription.add(mInteractor.requestGetEstablishmentRatingPost(codUnidade)
                .observeOn(AndroidSchedulers.mainThread())
                .onErrorReturn(throwable -> null)
                .subscribe(listResponse -> {
                    if (listResponse != null && listResponse.isSuccessful()) {
                        if (listResponse.body() != null && listResponse.body().size() > 0) {
                            mInteractor.addEstablishmentToRatingList(listResponse.body().get(0).getCodPostagem(), codUnidade);
                            if (listResponse.body().get(0).getConteudos().size() > 0) {
                                mInteractor.addEstablishmentToContentList(listResponse.body().
                                                get(0).getConteudos().get(0).getCodConteudoPostagem()
                                        , codUnidade);
                            }
                            mInteractor.requestEstablishmentRating(codUnidade)
                                    .observeOn(AndroidSchedulers.mainThread())
                                    .onErrorReturn(throwable -> null)
                                    .subscribe(responseBodyResponse -> {
                                        mEstablishmentProgress.setVisibility(View.GONE);
                                        if (responseBodyResponse == null) {
                                            mView.showToast(mContext.getString(R.string.error_get_establishment_review));
                                        } else {
                                            mRatingView.setIndicator(false);
                                            if (responseBodyResponse.isSuccessful()) {
                                                mRatingView.setRating(responseBodyResponse.body().getMedia());
                                            }
                                        }
                                    });
                        } else {
                            mEstablishmentProgress.setVisibility(View.GONE);
                            mSubscription.add(mInteractor.requestCreateRatingPost(codUnidade)
                                    .observeOn(AndroidSchedulers.mainThread())
                                    .onErrorReturn(throwable -> null)
                                    .retry(3)
                                    .subscribe());
                        }
                    } else {
                        mView.showToast(mContext.getString(R.string.error_get_establishment_review));
                    }
                }));
    }

    private void showEmergencyBottomSheetDialog() {
        BottomSheetDialog bottomSheetDialog = new BottomSheetDialog(mContext);

        View dialogView = LayoutInflater.from(mContext).inflate(R.layout.dialog_bottom_sheet_emergency, null);
        EmergencyViews emergencyViews = new EmergencyViews();
        ButterKnife.bind(emergencyViews, dialogView);

        bottomSheetDialog.setContentView(dialogView);
        bottomSheetDialog.getWindow().findViewById(R.id.design_bottom_sheet)
                .setBackgroundResource(R.color.default_dialog_background);

        emergencyViews.mainInfoCard.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);

        emergencyViews.samuLayout.setOnClickListener(v -> {
            mView.showSamuDialog((dialog, which) -> {
                Intent intent = new Intent(Intent.ACTION_DIAL);
                intent.setData(Uri.parse("tel:" + 192));
                mContext.startActivity(intent);
            });
        });

        emergencyViews.firemanLayout.setOnClickListener(v -> {
            mView.showFiremanDialog((dialog, which) -> {
                Intent intent = new Intent(Intent.ACTION_DIAL);
                intent.setData(Uri.parse("tel:" + 193));
                mContext.startActivity(intent);
            });
        });

        emergencyViews.policeLayout.setOnClickListener(v -> {
            mView.showPoliceDialog((dialog, which) -> {
                Intent intent = new Intent(Intent.ACTION_DIAL);
                intent.setData(Uri.parse("tel:" + 190));
                mContext.startActivity(intent);
            });
        });

        BottomSheetBehavior mBehavior = BottomSheetBehavior.from((View) dialogView.getParent());
        mBehavior.setPeekHeight(emergencyViews.mainInfoCard.getMeasuredHeight() + 115);

        bottomSheetDialog.show();
    }

    private void showEstablishmentBottomDialog(Establishment establishment) {
        if (establishment == null) {
            return;
        }
        BottomSheetDialog bottomSheetDialog = new BottomSheetDialog(mContext);

        View dialogView = LayoutInflater.from(mContext).inflate(R.layout.dialog_bottom_sheet_marker, null);
        MarkerViews bottomViews = new MarkerViews();
        ButterKnife.bind(bottomViews, dialogView);

        mRatingView = bottomViews.ratingView;
        mRatingView.setIndicator(true);
        mEstablishmentProgress = bottomViews.establishmentProgress;
        mEstablishmentProgress.setVisibility(View.VISIBLE);

        bottomViews.establishmentTitle.setText(GenericUtil.capitalize(establishment.getNomeFantasia().toLowerCase()));
        bottomViews.descricaoCompletaText.setText(GenericUtil.capitalize(establishment.getDescricaoCompleta().toLowerCase()));
        bottomViews.enderecoText.setText(mInteractor.getAddressText(establishment.getLogradouro(), establishment.getNumero(),
                establishment.getBairro(), establishment.getCidade(), establishment.getUf(), establishment.getCep()));
        if (TextUtils.isEmpty(establishment.getTelefone())) {
            bottomViews.phoneLayout.setVisibility(View.GONE);
        } else {
            bottomViews.phoneText.setText(establishment.getTelefone());
        }
        bottomViews.turnoAtendimento.setText(establishment.getTurnoAtendimento());
        bottomViews.tipoUnidadeText.setText(GenericUtil.capitalize(establishment.getTipoUnidade().toLowerCase()));
        bottomViews.redeAtendimentoText.setText(GenericUtil.capitalize(establishment.getEsferaAdministrativa().toLowerCase()));
        bottomViews.vinculoSusText.setText(GenericUtil.capitalize(establishment.getVinculoSus().toLowerCase()));
        bottomViews.fluxoClientelaText.setText(mInteractor.getFluxoClientelaText(establishment.getFluxoClientela()));
        bottomViews.cnpjText.setText(establishment.getCnpj());
        bottomViews.servicesText.setText(mInteractor.getServicesText(establishment));
        bottomViews.enderecoText.setOnClickListener(view -> {
            showGoToAddressDialog(establishment.getLatitude(), establishment.getLongitude());
        });

        bottomViews.phoneText.setOnClickListener(v -> {
            showCallToPhoneDialog(establishment.getTelefone());
        });

        if (mInteractor.isEstablishmentLiked(Long.valueOf(establishment.getCodUnidade()))) {
            bottomViews.likeImage.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_like_filled));
        }

        bottomViews.groupImage.setOnClickListener(v -> {
            Intent intent = new Intent(mContext, GroupActivity.class);
            intent.putExtra(ESTABLISHMENT_INTENT_KEY, establishment.getNomeFantasia());
            mView.goToActivity(intent);
        });

        isLiked = mInteractor.isEstablishmentLiked(Long.valueOf(establishment.getCodUnidade()));
        bottomViews.likeImage.setOnClickListener(v -> {
            mEstablishmentProgress.setVisibility(View.VISIBLE);
            if (isLiked) {
                mSubscription.add(mInteractor.requestDisLikeEstablishment(establishment.getCodUnidade())
                        .observeOn(AndroidSchedulers.mainThread())
                        .onErrorReturn(throwable -> null)
                        .subscribe(responseBodyResponse -> {
                            mEstablishmentProgress.setVisibility(View.GONE);
                            if (responseBodyResponse != null && responseBodyResponse.isSuccessful()) {
                                isLiked = false;
                                mInteractor.removeDislikedContentCode();
                                bottomViews.likeImage.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_like_empty));
                            } else {
                                mView.showToast(mContext.getString(R.string.http_error_generic));
                            }
                        }));
            } else {
                requestLikeEstablishment(Long.valueOf(establishment.getCodUnidade()), bottomViews.likeImage);
            }
        });

        bottomSheetDialog.setContentView(dialogView);
        bottomSheetDialog.getWindow().findViewById(R.id.design_bottom_sheet)
                .setBackgroundResource(R.color.default_dialog_background);

        bottomViews.mainInfoCard.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);

        BottomSheetBehavior mBehavior = BottomSheetBehavior.from((View) dialogView.getParent());
        mBehavior.setPeekHeight(bottomViews.mainInfoCard.getMeasuredHeight() + 115);

        bottomSheetDialog.setOnDismissListener(dialogInterface -> {
            lastOpenned.hideInfoWindow();
        });

        bottomSheetDialog.show();
    }

    @Override
    public void onLocationFound(Location location) {
        mMap.setMyLocationEnabled(true);
        if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        mLocation = location;
        mInteractor.requestUserUf(location.getLatitude(), location.getLongitude(), this);
        updateMapLocation();
        requestEstablishments(0);
    }

    private void updateMapLocation() {
        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(
                new LatLng(mLocation.getLatitude(),
                        mLocation.getLongitude()),
                DEFAULT_ZOOM));
    }

    private void requestLikeEstablishment(Long codUnidade, ImageView likeImage) {
        mEstablishmentProgress.setVisibility(View.VISIBLE);
        mSubscription.add(mInteractor.requestLikeEstablishment(String.valueOf(codUnidade))
                .observeOn(AndroidSchedulers.mainThread())
                .onErrorReturn(throwable -> null)
                .subscribe(likeResponse -> {
                    mEstablishmentProgress.setVisibility(View.GONE);
                    if (likeResponse != null && likeResponse.isSuccessful()) {
                        isLiked = true;
                        mInteractor.addEstablishmentToLikedList(GenericUtil.getContentIdFromUrl(String.valueOf(mInteractor.getPostCode()),
                                likeResponse.headers().get("location")), codUnidade);
                        likeImage.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_like_filled));
                    } else {
                        mView.showToast(mContext.getString(R.string.http_error_generic));
                    }
                }));
    }

    private void requestEstablishmentRating(Long codUnidade) {
        mEstablishmentProgress.setVisibility(View.VISIBLE);
        mSubscription.add(mInteractor.requestGetEstablishmentRatingPost(codUnidade)
                .observeOn(AndroidSchedulers.mainThread())
                .onErrorReturn(throwable -> null)
                .subscribe(listResponse -> {
                    if (listResponse != null && listResponse.isSuccessful()) {
                        if (listResponse.body() != null && listResponse.body().size() > 0) {
                            if (listResponse.body().get(0).getConteudos().size() > 0) {
                                mInteractor.requestEstablishmentRating(codUnidade)
                                        .observeOn(AndroidSchedulers.mainThread())
                                        .onErrorReturn(throwable -> null)
                                        .subscribe(responseBodyResponse -> {
                                            mEstablishmentProgress.setVisibility(View.GONE);
                                            if (responseBodyResponse == null) {
                                                mView.showToast(mContext.getString(R.string.error_get_establishment_review));
                                            } else {
                                                if (responseBodyResponse.isSuccessful()) {
                                                    mRatingView.setRating(responseBodyResponse.body().getMedia());
                                                }
                                            }
                                        });
                            } else {
                                mEstablishmentProgress.setVisibility(View.GONE);
                            }
                        } else {
                            mEstablishmentProgress.setVisibility(View.GONE);
                            mSubscription.add(mInteractor.requestCreateRatingPost(codUnidade)
                                    .observeOn(AndroidSchedulers.mainThread())
                                    .onErrorReturn(throwable -> null)
                                    .retry(3)
                                    .subscribe());
                        }
                    } else {
                        mView.showToast(mContext.getString(R.string.error_get_establishment_review));
                    }
                }));
    }

    private void requestEstablishments(int pagination) {
        mLastObservable = mInteractor.requestEstablishmentsByLocation(mLocation, pagination);
        mLastObserver = requestEstablishmentsObserver;
        mSubscription.add(mInteractor.requestEstablishmentsByLocation(mLocation, pagination)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(requestEstablishmentsObserver));
    }

    private void showMapPins(List<Establishment> establishmentList) {
        for (Establishment establishment : establishmentList) {
            mInteractor.drawEstablishment(mMap, establishment);
        }
    }

    private void showGoToAddressDialog(Double latitude, Double longitude) {
        AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
        builder.setTitle(R.string.location_dialog_title);
        builder.setMessage(mContext.getString(R.string.location_dialog_message));
        builder.setPositiveButton(R.string.location_dialog_positive, (dialogInterface, i) -> {
            Intent intent = new Intent(Intent.ACTION_VIEW,
                    Uri.parse("http://maps.google.com/maps?daddr=" + latitude + "," + longitude));
            mView.goToActivity(intent);
        });
        builder.setNegativeButton(R.string.location_dialog_negative, (dialogInterface, i) -> {
        });
        builder.create().show();
    }

    private void showCallToPhoneDialog(String telefone) {
        AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
        builder.setTitle(R.string.call_dialog_title);
        builder.setMessage(mContext.getString(R.string.call_dialog_message) + telefone + "?");
        builder.setPositiveButton(R.string.call_dialog_positive, (dialogInterface, i) -> {
            Intent intent = new Intent(Intent.ACTION_DIAL);
            intent.setData(Uri.parse("tel:" + telefone));
            mContext.startActivity(intent);
        });
        builder.setNegativeButton(R.string.call_dialog_negative, (dialogInterface, i) -> {
        });
        builder.create().show();
    }

    private List<Establishment> mFilteredEstablishmentList = new ArrayList<>();
    private Observer<Response<List<Establishment>>> requestEstablishmentsObserver = new Observer<Response<List<Establishment>>>() {
        @Override
        public void onCompleted() {
        }

        @Override
        public void onError(Throwable e) {
            Log.d(TAG, "onError() called with: " + "e = [" + e + "]");
            mView.setProgressFabVisibility(View.GONE);
            mView.showNoConnectionSnackBar();
        }

        @Override
        public void onNext(Response<List<Establishment>> listResponse) {
            if (listResponse.isSuccessful()) {
                mEstablishmentList.addAll(listResponse.body());
                mFilteredEstablishmentList.addAll(listResponse.body());
                if (mEstablishmentList.size() > 0) {
                    showMapPins(listResponse.body());
                    if (listResponse.body().size() == ESTABLISHMENT_SEARCH_LIMIT) {
                        requestEstablishments(mEstablishmentList.size());
                    }
                    if (mEstablishmentList.size() <= ESTABLISHMENT_SEARCH_LIMIT) {
                        mInteractor.animateCameraToAllEstablishments(mMap);
                    }
                    mView.toggleFabButton(true);
                    mView.setProgressFabVisibility(View.GONE);
                } else {
                    mView.toggleFabButton(false);
                    mView.showToast(mContext.getString(R.string.establishment_no_results));
                    mView.setProgressFabVisibility(View.GONE);
                }
            } else {
                try {
                    Error401 error401 = new Gson().fromJson(listResponse.errorBody().string(), Error401.class);
                    mView.showToast(error401.getMessageList().get(0).getText());
                } catch (Exception e) {
                    mView.showToast(mContext.getString(R.string.http_error_generic));
                }
                mView.setProgressFabVisibility(View.GONE);
                mView.showNoConnectionSnackBar();
            }
        }
    };

    @Override
    public void onNext(String uf) {
        try {
            mView.setUfSpinnerSelection(mUfList.indexOf(uf));
        } catch (Exception e) {}
    }

    class EmergencyViews {
        @Bind(R.id.main_info_card)
        LinearLayout mainInfoCard;
        @Bind(R.id.bottom_sheet)
        NestedScrollView bottomSheet;
        @Bind(R.id.samu_layout)
        LinearLayout samuLayout;
        @Bind(R.id.fireman_layout)
        LinearLayout firemanLayout;
        @Bind(R.id.police_layout)
        LinearLayout policeLayout;
    }

    class MarkerViews {
        @Bind(R.id.establishment_title)
        TextView establishmentTitle;
        @Bind(R.id.descricao_completa_text)
        TextView descricaoCompletaText;
        @Bind(R.id.endereco_text)
        TextView enderecoText;
        @Bind(R.id.phone_text)
        TextView phoneText;
        @Bind(R.id.main_info_card)
        LinearLayout mainInfoCard;
        @Bind(R.id.tipo_unidade_text)
        TextView tipoUnidadeText;
        @Bind(R.id.rede_atendimento_text)
        TextView redeAtendimentoText;
        @Bind(R.id.vinculo_sus_text)
        TextView vinculoSusText;
        @Bind(R.id.fluxo_clientela_text)
        TextView fluxoClientelaText;
        @Bind(R.id.cnpj_text)
        TextView cnpjText;
        @Bind(R.id.turno_atendimento_text)
        TextView turnoAtendimento;
        @Bind(R.id.services_text)
        TextView servicesText;
        @Bind(R.id.bottom_sheet)
        NestedScrollView bottomSheet;
        @Bind(R.id.phone_layout)
        LinearLayout phoneLayout;
        @Bind(R.id.establishment_like_image)
        ImageView likeImage;
        @Bind(R.id.group_image)
        ImageView groupImage;
        @Bind(R.id.rating_view)
        SimpleRatingBar ratingView;
        @Bind(R.id.establishment_progress)
        ProgressBar establishmentProgress;
    }
}