package com.joker.rxweather.views.activity;

import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.TextInputLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.animation.AccelerateInterpolator;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import butterknife.Bind;
import butterknife.OnClick;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.jakewharton.rxbinding.widget.RxTextView;
import com.joker.rxweather.MyApplication;
import com.joker.rxweather.R;
import com.joker.rxweather.common.Constants;
import com.joker.rxweather.common.Utils;
import com.joker.rxweather.common.event.FinishActEvent;
import com.joker.rxweather.common.rx.rxAndroid.SimpleObserver;
import com.joker.rxweather.common.rx.rxAndroid.schedulers.AndroidSchedulers;
import com.joker.rxweather.common.rx.rxbus.RxBus;
import com.joker.rxweather.model.entities.SearchEntity;
import com.joker.rxweather.presenter.SearchPresenter;
import com.joker.rxweather.presenter.SearchPresenterImp;
import com.joker.rxweather.ui.ProgressLayout;
import com.joker.rxweather.ui.animation.SupportAnimator;
import com.joker.rxweather.ui.animation.ViewAnimationUtils;
import com.joker.rxweather.ui.widget.RevealFrameLayout;
import com.joker.rxweather.views.SearchView;
import com.trello.rxlifecycle.ActivityEvent;
import java.lang.ref.WeakReference;
import java.util.concurrent.TimeUnit;
import rx.Observable;
import rx.functions.Func1;
import rx.subscriptions.CompositeSubscription;

/**
 * Created by Joker on 2015/11/4.
 */
public class SearchActivity extends BaseActivity implements SearchView<Observable<SearchEntity>> {

    private static final String TAG = SearchActivity.class.getSimpleName();

    @Nullable
    @Bind(R.id.search_layout_root_view)
    RelativeLayout rootView;
    @Nullable
    @Bind(R.id.toolbar_layout_root_view)
    Toolbar toolbar;
    @Nullable
    @Bind(R.id.toolbar_layout_title_tv)
    TextView titleTv;

    @Nullable
    @Bind(R.id.search_layout_reveal_view)
    RevealFrameLayout revealFrameLayout;
    @Nullable
    @Bind(R.id.search_layout_pl)
    ProgressLayout progressLayout;

    @Nullable
    @Bind(R.id.search_layout_ill)
    TextInputLayout inputLayout;
    @Nullable
    @Bind(R.id.search_layout_et)
    EditText editText;
    @Nullable
    @Bind(R.id.search_layout_text_tv)
    TextView weatherTv;
    @Nullable
    @Bind(R.id.search_layout_text_iv)
    ImageView weatherIv;

    /*要查询的城市名称*/
    private String cityName;

    private SearchPresenter<SearchView<Observable<SearchEntity>>> searchPresenter;
    private Observable<SearchEntity> cacheObservable;

    private RxBus rxBus;
    private WeakReference<AppCompatActivity> weakReference;

    private CompositeSubscription compositeSubscription = new CompositeSubscription();

    private View.OnClickListener retryClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            SearchActivity.this.searchPresenter.search(cityName);
        }
    };

    public static void navigateToSearch(AppCompatActivity startingActivity) {
        Intent intent = new Intent(startingActivity, SearchActivity.class);
        startingActivity.startActivity(intent);
    }

    @Override
    protected int getLayoutId() {
        return R.layout.search_layout;
    }

    @Override
    protected void onCreated() {
        searchPresenter = new SearchPresenterImp();
        searchPresenter.attachView(SearchActivity.this);
    }

    @Override
    protected void initView(Bundle savedInstanceState) {
        SearchActivity.this.setSupportActionBar(toolbar);
        SearchActivity.this.getSupportActionBar().setTitle("");

        this.titleTv.setText(getResources().getString(R.string.bottom_bar_search));
        this.inputLayout.setHint(getResources().getString(R.string.hint));

        SearchActivity.this.setListener();

        if (savedInstanceState == null) {
            rootView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                @Override
                public boolean onPreDraw() {
                    rootView.getViewTreeObserver().removeOnPreDrawListener(this);
                    SearchActivity.this.runEnterAnim();
                    return true;
                }
            });
        } else {

            SearchEntity searchEntity = (SearchEntity) savedInstanceState.getSerializable(Constants.CACHE);
            SearchActivity.this.cityName = (String) savedInstanceState.getSerializable(Constants.CACHE_CITY);

            if (searchEntity != null) {
                SearchActivity.this.showResult(Observable.just(searchEntity));
            } else if (!TextUtils.isEmpty(cityName)) {
                searchPresenter.search(cityName);
            }
        }
    }

    private void setListener() {

        this.compositeSubscription.add(RxTextView.textChanges(editText)
                                                 .skip(1)
                                                 .debounce(Constants.MILLISECONDS_600, TimeUnit.MILLISECONDS)
                                                 .switchMap(new Func1<CharSequence, Observable<CharSequence>>() {
                                                     @Override
                                                     public Observable<CharSequence> call(CharSequence charSequence) {
                                                         return Observable.just(charSequence);
                                                     }
                                                 })
                                                 .observeOn(AndroidSchedulers.mainThread())
                                                 .compose(SearchActivity.this.<CharSequence>bindUntilEvent(ActivityEvent.DESTROY))
                                                 .subscribe(new SimpleObserver<CharSequence>() {
                                                     @Override
                                                     public void onNext(CharSequence charSequence) {

                                                         String temp = charSequence.toString();
                                                         if (!TextUtils.isEmpty(temp.trim()) &&
                                                                 !temp.equals(SearchActivity.this.cityName)) {

                                                             SearchActivity.this.cityName =
                                                                     charSequence.toString().trim();
                                                             SearchActivity.this.searchPresenter.search(cityName);
                                                         }
                                                     }
                                                 }));
    }

    @Override
    protected void onSaveInstanceState(final Bundle outState) {
        super.onSaveInstanceState(outState);

        if (cacheObservable != null) {
            this.compositeSubscription.add(cacheObservable//
                                                          .compose(SearchActivity.this.<SearchEntity>bindUntilEvent(
                                                                  ActivityEvent.DESTROY))
                                                          .subscribe(new SimpleObserver<SearchEntity>() {
                                                              @Override
                                                              public void onNext(SearchEntity searchEntity) {
                                                                  outState.putSerializable(Constants.CACHE,
                                                                                           searchEntity);
                                                                  outState.putSerializable(Constants.CACHE_CITY,
                                                                                           SearchActivity.this.cityName);
                                                              }
                                                          }));
        }
    }

    private void runEnterAnim() {

        final Rect bounds = new Rect();
        revealFrameLayout.getHitRect(bounds);

        SearchActivity.this.revealFrameLayout.setLayerType(View.LAYER_TYPE_HARDWARE, null);

        SupportAnimator revealAnimator = ViewAnimationUtils.createCircularReveal(revealFrameLayout.getChildAt(0),
                                                                                 0,
                                                                                 bounds.left,
                                                                                 0,
                                                                                 Utils.pythagorean(bounds.width(),
                                                                                                   bounds.height()));
        revealAnimator.setDuration(Constants.MILLISECONDS_400);
        revealAnimator.setInterpolator(new AccelerateInterpolator());
        revealAnimator.addListener(new SupportAnimator.SimpleAnimatorListener() {
            @Override
            public void onAnimationEnd() {
                SearchActivity.this.revealFrameLayout.setLayerType(View.LAYER_TYPE_NONE, null);
            }
        });
        revealAnimator.start();
    }

    @OnClick(R.id.bottom_bar_forecast_tv)
    void onForecastClick() {
        SearchActivity.this.finish();
        overridePendingTransition(0, 0);
    }

    @Override
    public void showSearchResult(Observable<SearchEntity> searchEntityObservable) {
        SearchActivity.this.showResult(searchEntityObservable);
    }

    private void showResult(Observable<SearchEntity> searchEntityObservable) {

        this.cacheObservable = searchEntityObservable;

        this.compositeSubscription.add(cacheObservable.compose(SearchActivity.this.<SearchEntity>bindUntilEvent(
                ActivityEvent.DESTROY)).subscribe(new SimpleObserver<SearchEntity>() {
            @Override
            public void onNext(SearchEntity searchEntity) {

                SearchActivity.this.weatherTv.setText(
                        Utils.formatTemp(searchEntity.currentTemp) + "  ,  " + searchEntity.weatherText);

                Glide.with(SearchActivity.this)
                     .load(Constants.ICON_URL + searchEntity.weatherCode + ".png")
                     .dontAnimate()
                     .placeholder(R.drawable.holding_icon)
                     .error(R.drawable.holding_icon)
                     .diskCacheStrategy(DiskCacheStrategy.RESULT)
                     .into(SearchActivity.this.weatherIv);
            }
        }));
    }

    @Override
    public boolean isContent() {
        return progressLayout.isContent();
    }

    @Override
    public void showLoading() {
        progressLayout.showLoading();
    }

    @Override
    public void showContent() {
        if (!progressLayout.isContent()) progressLayout.showContent();
    }

    @Override
    public void showError(int messageId) {
        if (!progressLayout.isError()) progressLayout.showError(messageId, retryClickListener);
    }

    @Override
    public Context getContext() {

        if (weakReference == null) {
            weakReference = new WeakReference<AppCompatActivity>(SearchActivity.this);
        }

        return weakReference.get();
    }

    @Override
    protected void exit() {
        if (rxBus == null) rxBus = MyApplication.get().getRxBus();
        rxBus.postEvent(new FinishActEvent());
    }

    @Override
    protected void onDestroy() {
        if (this.compositeSubscription.hasSubscriptions()) this.compositeSubscription.clear();
        super.onDestroy();

        this.searchPresenter.detachView();
    }
}
