package io.homeassistant.android.view.viewholders;
import android.content.res.ColorStateList;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LevelListDrawable;
import android.os.Handler;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.SwitchCompat;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.widget.SeekBar;
import io.homeassistant.android.Common;
import io.homeassistant.android.HassActivity;
import io.homeassistant.android.R;
import io.homeassistant.android.api.Attribute;
import io.homeassistant.android.api.HassUtils;
import io.homeassistant.android.api.requests.ToggleRequest;
import static io.homeassistant.android.api.Domain.LIGHT;
import static io.homeassistant.android.api.Domain.SWITCH;
public class SwitchViewHolder extends TextViewHolder implements View.OnTouchListener, View.OnClickListener {
private final SwitchCompat stateSwitch;
private final SeekBar brightnessSlider;
private final Handler handler = new Handler();
private final Runnable touchDisallowRunnable = () -> itemView.getParent().requestDisallowInterceptTouchEvent(true);
private final SliderRunnable sliderRunnable = new SliderRunnable();
public SwitchViewHolder(View itemView) {
super(itemView);
stateSwitch = (SwitchCompat) itemView.findViewById(R.id.state_switch);
stateSwitch.setOnClickListener(null);
brightnessSlider = (SeekBar) itemView.findViewById(R.id.brightness_slider);
sliderRunnable.lastEvent = null;
name.setOnTouchListener(null);
}
@Override
protected void updateViews() {
super.updateViews();
stateSwitch.setChecked(entity.state.equals(HassUtils.getOnState(entity, true)));
stateSwitch.setOnClickListener(this);
if ((entity.attributes.getInt(Attribute.SUPPORTED_FEATURES) & Common.LIGHT_SUPPORTS_BRIGHTNESS) == Common.LIGHT_SUPPORTS_BRIGHTNESS) {
brightnessSlider.setProgress(entity.attributes.get(Attribute.BRIGHTNESS, (Number) 0).intValue());
name.setOnTouchListener(this);
}
updateColor();
}
private void updateColor() {
Drawable leftDrawable = name.getCompoundDrawablesRelative()[0];
String domain = entity.getDomain();
if (leftDrawable != null && (domain.equals(LIGHT) || domain.equals(SWITCH))) {
if (!(leftDrawable instanceof LevelListDrawable)) {
LevelListDrawable levelListDrawable = new LevelListDrawable();
// Add states
levelListDrawable.addLevel(1, 1, leftDrawable);
BitmapDrawable enabledDrawable = (BitmapDrawable) leftDrawable.getConstantState().newDrawable().mutate();
enabledDrawable.setTintList(ColorStateList.valueOf(ContextCompat.getColor(name.getContext(), R.color.color_activated)));
levelListDrawable.addLevel(2, 2, enabledDrawable);
// Restore bounds
levelListDrawable.setBounds(0, 0, name.getResources().getDimensionPixelSize(R.dimen.icon_size), name.getResources().getDimensionPixelSize(R.dimen.icon_size));
// Set drawable
name.setCompoundDrawablesRelative(levelListDrawable, null, null, null);
leftDrawable = levelListDrawable;
}
leftDrawable.setLevel(entity.state.equals(HassUtils.getOnState(entity, false)) ? 1 : 2);
}
}
@Override
public void onClick(View v) {
HassActivity activity = (HassActivity) v.getContext();
activity.send(new ToggleRequest(entity, stateSwitch.isChecked()), (success, result) -> {
if (success) {
entity.state = HassUtils.getOnState(entity, stateSwitch.isChecked());
updateColor();
} else {
stateSwitch.toggle();
}
});
}
@Override
public boolean onTouch(View v, MotionEvent event) {
brightnessSlider.getLayoutParams().height = name.getHeight();
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
sliderRunnable.previousProgress = brightnessSlider.getProgress();
sliderRunnable.lastEvent = event;
sliderRunnable.moved = false;
handler.postDelayed(touchDisallowRunnable, 200);
handler.postDelayed(sliderRunnable, 800);
return true;
case MotionEvent.ACTION_MOVE:
sliderRunnable.lastEvent = event;
if (brightnessSlider.getVisibility() == View.VISIBLE && considerMoved(event)) {
brightnessSlider.dispatchTouchEvent(event);
}
return true;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
handler.removeCallbacks(touchDisallowRunnable);
handler.removeCallbacks(sliderRunnable);
if (brightnessSlider.getProgress() != sliderRunnable.previousProgress) { // Changed
HassActivity activity = (HassActivity) brightnessSlider.getContext();
activity.send(new ToggleRequest(entity, brightnessSlider.getProgress()), (success, result) -> {
if (success) {
stateSwitch.setChecked(brightnessSlider.getProgress() > 0);
entity.state = HassUtils.getOnState(entity, brightnessSlider.getProgress() > 0);
updateColor();
} else {
brightnessSlider.setProgress(sliderRunnable.previousProgress);
}
});
}
brightnessSlider.setVisibility(View.GONE);
name.setVisibility(View.VISIBLE);
return true;
default:
return false;
}
}
private boolean considerMoved(MotionEvent event) {
return (sliderRunnable.moved = sliderRunnable.moved || event.getHistorySize() >= 1 && Math.abs(event.getX() - event.getHistoricalX(0)) > 30f);
}
private class SliderRunnable implements Runnable {
int previousProgress;
MotionEvent lastEvent;
boolean moved;
@Override
public void run() {
name.setVisibility(View.INVISIBLE);
brightnessSlider.setVisibility(View.VISIBLE);
ViewAnimationUtils.createCircularReveal(brightnessSlider, (int) lastEvent.getRawX(), (int) lastEvent.getRawY(), 0, itemView.getWidth())
.setDuration(300).start();
}
}
}