<commit_before>package com.fred.inventory.presentation.productlist.viewmodels;

import android.databinding.ObservableField;
import android.databinding.ObservableInt;
import android.support.v7.widget.RecyclerView;
import android.text.TextWatcher;
import android.view.View;
import com.fred.inventory.R;
import com.fred.inventory.domain.models.Product;
import com.fred.inventory.domain.models.ProductList;
import com.fred.inventory.domain.usecases.GetProductInfoFromCodeUseCase;
import com.fred.inventory.domain.usecases.GetProductListUseCase;
import com.fred.inventory.domain.usecases.SaveProductListInLocalStorageUseCase;
import com.fred.inventory.presentation.items.ItemScreen;
import com.fred.inventory.presentation.productlist.adapters.ProductListRecyclerViewAdapter;
import com.fred.inventory.utils.StringUtils;
import com.fred.inventory.utils.binding.Observable;
import com.fred.inventory.utils.binding.Observer;
import com.fred.inventory.utils.binding.widgets.OneTimeTextWatcher;
import com.fred.inventory.utils.path.PathManager;
import com.fred.inventory.utils.rx.RxSubscriptionPool;
import com.fred.inventory.utils.rx.schedulers.SchedulerTransformer;
import com.fred.inventory.utils.rx.schedulers.qualifiers.IOToUiSchedulerTransformer;
import javax.inject.Inject;
import rx.Subscriber;
import rx.Subscription;
import rx.functions.Func1;
import timber.log.Timber;

public class ProductListViewModelImpl
    implements ProductListViewModel, ProductListRecyclerViewAdapter.OnProductDeletedListener,
    ProductListRecyclerViewAdapter.OnItemClickListener {
  private final ObservableField<String> productListName = new ObservableField<>();
  private final OneTimeTextWatcher productNameTextWatcher = new OneTimeTextWatcher(productListName);
  private final GetProductListUseCase getProductListUseCase;
  private final SaveProductListInLocalStorageUseCase saveProductListInLocalStorageUseCase;
  private final SchedulerTransformer transformer;
  private final RxSubscriptionPool rxSubscriptionPool;
  private final ObservableInt listVisibility = new ObservableInt(View.GONE);
  private final ObservableInt emptyListVisibility = new ObservableInt(View.GONE);
  private final ObservableInt progressBarVisibility = new ObservableInt(View.GONE);
  private final Observable<Long> productListIdObservable = Observable.create();
  private final PathManager pathManager;
  private final ProductListRecyclerViewAdapter adapter;
  private final GetProductInfoFromCodeUseCase getProductInfoFromCodeUseCase;

  private ProductList productList;
  private OnScanBarCodeButtonClickListener scanBarCodeButtonClickListener;

  @Inject public ProductListViewModelImpl(GetProductListUseCase getProductListUseCase,
      SaveProductListInLocalStorageUseCase saveProductListInLocalStorageUseCase,
      @IOToUiSchedulerTransformer SchedulerTransformer transformer,
      RxSubscriptionPool rxSubscriptionPool, PathManager pathManager,
      ProductListRecyclerViewAdapter adapter,
      GetProductInfoFromCodeUseCase getProductInfoFromCodeUseCase) {
    this.getProductListUseCase = getProductListUseCase;
    this.saveProductListInLocalStorageUseCase = saveProductListInLocalStorageUseCase;
    this.transformer = transformer;
    this.rxSubscriptionPool = rxSubscriptionPool;
    this.pathManager = pathManager;
    this.adapter = adapter;
    this.getProductInfoFromCodeUseCase = getProductInfoFromCodeUseCase;
  }

  @Override public void forProductList(Long id) {
    productListIdObservable.set(id);
  }

  @Override public void onActivityCreated() {
    adapter.setOnProductDeletedListener(this);
    adapter.setOnItemClickListener(this);

    if (productListIdObservable.get() == null) {
      emptyListVisibility.set(View.VISIBLE);
      // TODO: put input in text view
      return;
    }

    progressBarVisibility.set(View.VISIBLE);
    queryForProductList();
  }

  @Override public void onDestroyView() {
    rxSubscriptionPool.unsubscribeFrom(getClass().getCanonicalName());
  }

  @Override public ObservableField<String> productListName() {
    return productListName;
  }

  @Override public TextWatcher productNameTextWatcher() {
    return productNameTextWatcher;
  }

  @Override public ObservableInt progressBarVisibility() {
    return progressBarVisibility;
  }

  private void queryForProductList() {
    Subscription subscription = getProductListUseCase.get(productListIdObservable.get())
        .compose(transformer.applySchedulers())
        .subscribe(new ProductListSubscriber());

    rxSubscriptionPool.addSubscription(getClass().getCanonicalName(), subscription);
  }

  @Override public void onDoneButtonClick(View view) {
    final String name = productListName.get();
    if (StringUtils.isBlank(name)) {
      // TODO: Set error
      return;
    }

    ProductList productList = createFromInput();
    productList.setProducts(adapter.getItems());

    Subscription subscription = saveProductListInLocalStorageUseCase.save(productList)
        .compose(transformer.applySchedulers())
        .subscribe(value -> pathManager.back(), e -> Timber.d(e, "Failed to save product list"));

    rxSubscriptionPool.addSubscription(getClass().getCanonicalName(), subscription);
  }

  @Override
  public void setOnScanBarCodeButtonClickListener(OnScanBarCodeButtonClickListener listener) {
    this.scanBarCodeButtonClickListener = listener;
  }

  @Override public void onScanBarCodeButtonClick(View view) {
    String name = productListName.get();
    if (StringUtils.isBlank(name)) {
      // TODO: Show error here
      return;
    }

    if (scanBarCodeButtonClickListener != null) {
      scanBarCodeButtonClickListener.onScanBarCodeButtonClicked();
    }
  }

  @Override public void onAddButtonClick(View view) {
    String name = productListName.get();
    if (StringUtils.isBlank(name)) {
      // TODO: Show error here
      return;
    }

    ProductList productList = createFromInput();
    productList.setProducts(adapter.getItems());

    Subscription subscription = saveProductListInLocalStorageUseCase.save(productList)
        .compose(transformer.applySchedulers())
        .subscribe(value -> {
          ProductListViewModelImpl.this.productList = productList;
          goToItemScreen(productList, null);
        }, e -> Timber.d(e, "Failed to save product list"));

    rxSubscriptionPool.addSubscription(getClass().getCanonicalName(), subscription);
  }

  @Override public ObservableInt emptyListVisibility() {
    return emptyListVisibility;
  }

  @Override public ObservableInt itemListVisibility() {
    return listVisibility;
  }

  @Override public void unbindProductListIdObserver(Observer<Long> observer) {
    productListIdObservable.unbind(observer);
  }

  @Override public void bindProductListIdObserver(Observer<Long> observer) {
    productListIdObservable.bind(observer);
  }

  @Override public RecyclerView.Adapter<?> productListRecyclerViewAdapter() {
    return (RecyclerView.Adapter<?>) adapter;
  }

  private ProductList createFromInput() {<commit_msg>Can now add items on first run<commit_after>package com.fred.inventory.presentation.productlist.viewmodels;

import android.databinding.ObservableField;
import android.databinding.ObservableInt;
import android.support.v7.widget.RecyclerView;
import android.text.TextWatcher;
import android.view.View;
import com.fred.inventory.R;
import com.fred.inventory.domain.models.Product;
import com.fred.inventory.domain.models.ProductList;
import com.fred.inventory.domain.usecases.GetProductInfoFromCodeUseCase;
import com.fred.inventory.domain.usecases.GetProductListUseCase;
import com.fred.inventory.domain.usecases.SaveProductListInLocalStorageUseCase;
import com.fred.inventory.presentation.items.ItemScreen;
import com.fred.inventory.presentation.productlist.adapters.ProductListRecyclerViewAdapter;
import com.fred.inventory.utils.StringUtils;
import com.fred.inventory.utils.binding.Observable;
import com.fred.inventory.utils.binding.Observer;
import com.fred.inventory.utils.binding.widgets.OneTimeTextWatcher;
import com.fred.inventory.utils.path.PathManager;
import com.fred.inventory.utils.rx.RxSubscriptionPool;
import com.fred.inventory.utils.rx.schedulers.SchedulerTransformer;
import com.fred.inventory.utils.rx.schedulers.qualifiers.IOToUiSchedulerTransformer;
import javax.inject.Inject;
import rx.Subscriber;
import rx.Subscription;
import rx.functions.Func1;
import timber.log.Timber;

public class ProductListViewModelImpl
    implements ProductListViewModel, ProductListRecyclerViewAdapter.OnProductDeletedListener,
    ProductListRecyclerViewAdapter.OnItemClickListener {
  private final ObservableField<String> productListName = new ObservableField<>();
  private final OneTimeTextWatcher productNameTextWatcher = new OneTimeTextWatcher(productListName);
  private final GetProductListUseCase getProductListUseCase;
  private final SaveProductListInLocalStorageUseCase saveProductListInLocalStorageUseCase;
  private final SchedulerTransformer transformer;
  private final RxSubscriptionPool rxSubscriptionPool;
  private final ObservableInt listVisibility = new ObservableInt(View.GONE);
  private final ObservableInt emptyListVisibility = new ObservableInt(View.GONE);
  private final ObservableInt progressBarVisibility = new ObservableInt(View.GONE);
  private final Observable<Long> productListIdObservable = Observable.create();
  private final PathManager pathManager;
  private final ProductListRecyclerViewAdapter adapter;
  private final GetProductInfoFromCodeUseCase getProductInfoFromCodeUseCase;

  private ProductList productList;
  private OnScanBarCodeButtonClickListener scanBarCodeButtonClickListener;

  @Inject public ProductListViewModelImpl(GetProductListUseCase getProductListUseCase,
      SaveProductListInLocalStorageUseCase saveProductListInLocalStorageUseCase,
      @IOToUiSchedulerTransformer SchedulerTransformer transformer,
      RxSubscriptionPool rxSubscriptionPool, PathManager pathManager,
      ProductListRecyclerViewAdapter adapter,
      GetProductInfoFromCodeUseCase getProductInfoFromCodeUseCase) {
    this.getProductListUseCase = getProductListUseCase;
    this.saveProductListInLocalStorageUseCase = saveProductListInLocalStorageUseCase;
    this.transformer = transformer;
    this.rxSubscriptionPool = rxSubscriptionPool;
    this.pathManager = pathManager;
    this.adapter = adapter;
    this.getProductInfoFromCodeUseCase = getProductInfoFromCodeUseCase;
  }

  @Override public void forProductList(Long id) {
    productListIdObservable.set(id);
  }

  @Override public void onActivityCreated() {
    adapter.setOnProductDeletedListener(this);
    adapter.setOnItemClickListener(this);

    if (productListIdObservable.get() == null) {
      emptyListVisibility.set(View.VISIBLE);
      // TODO: put input in text view
      return;
    }

    progressBarVisibility.set(View.VISIBLE);
    queryForProductList();
  }

  @Override public void onDestroyView() {
    rxSubscriptionPool.unsubscribeFrom(getClass().getCanonicalName());
  }

  @Override public ObservableField<String> productListName() {
    return productListName;
  }

  @Override public TextWatcher productNameTextWatcher() {
    return productNameTextWatcher;
  }

  @Override public ObservableInt progressBarVisibility() {
    return progressBarVisibility;
  }

  private void queryForProductList() {
    Subscription subscription = getProductListUseCase.get(productListIdObservable.get())
        .compose(transformer.applySchedulers())
        .subscribe(new ProductListSubscriber());

    rxSubscriptionPool.addSubscription(getClass().getCanonicalName(), subscription);
  }

  @Override public void onDoneButtonClick(View view) {
    final String name = productListName.get();
    if (StringUtils.isBlank(name)) {
      // TODO: Set error
      return;
    }

    ProductList productList = createFromInput();
    productList.setProducts(adapter.getItems());

    Subscription subscription = saveProductListInLocalStorageUseCase.save(productList)
        .compose(transformer.applySchedulers())
        .subscribe(value -> pathManager.back(), e -> Timber.d(e, "Failed to save product list"));

    rxSubscriptionPool.addSubscription(getClass().getCanonicalName(), subscription);
  }

  @Override
  public void setOnScanBarCodeButtonClickListener(OnScanBarCodeButtonClickListener listener) {
    this.scanBarCodeButtonClickListener = listener;
  }

  @Override public void onScanBarCodeButtonClick(View view) {
    String name = productListName.get();
    if (StringUtils.isBlank(name)) {
      // TODO: Show error here
      return;
    }

    if (scanBarCodeButtonClickListener != null) {
      scanBarCodeButtonClickListener.onScanBarCodeButtonClicked();
    }
  }

  @Override public void onAddButtonClick(View view) {
    String name = productListName.get();
    if (StringUtils.isBlank(name)) {
      // TODO: Show error here
      return;
    }

    ProductList productList = createFromInput();
    productList.setProducts(adapter.getItems());

    Subscription subscription = saveProductListInLocalStorageUseCase.save(productList)
        .compose(transformer.applySchedulers())
        .subscribe(value -> {
          ProductListViewModelImpl.this.productList = value;
          goToItemScreen(value, null);
        }, e -> Timber.d(e, "Failed to save product list"));

    rxSubscriptionPool.addSubscription(getClass().getCanonicalName(), subscription);
  }

  @Override public ObservableInt emptyListVisibility() {
    return emptyListVisibility;
  }

  @Override public ObservableInt itemListVisibility() {
    return listVisibility;
  }

  @Override public void unbindProductListIdObserver(Observer<Long> observer) {
    productListIdObservable.unbind(observer);
  }

  @Override public void bindProductListIdObserver(Observer<Long> observer) {
    productListIdObservable.bind(observer);
  }

  @Override public RecyclerView.Adapter<?> productListRecyclerViewAdapter() {
    return (RecyclerView.Adapter<?>) adapter;
  }

  private ProductList createFromInput() {
{'fraction_non_alphanumeric': 0.08159189786748448, 'fraction_numerical': 0.0002852863561800157, 'mean_word_length': 5.353420933393747, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5533220', 'n_tokens_mistral': 3817, 'n_tokens_neox': 3750, 'n_words': 708}