/*
* Copyright (C) 2015 AChep@xda <artemchep@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package com.achep.acdisplay.services;
import android.content.Context;
import android.support.annotation.NonNull;
import com.achep.acdisplay.Config;
import com.achep.base.content.ConfigBase;
import com.achep.base.tests.Check;
/**
* Provides a callback when <b>something</b> should be started or stopped
* to satisfy any options or for power-save reason.
*
* @author Artem Chepurnoy
*/
public abstract class Switch {
private boolean mCreated;
@NonNull
private final Context mContext;
@NonNull
private final Callback mCallback;
/**
* Provides control callback to main service.
*
* @author Artem Chepurnoy
*/
public interface Callback {
/**
* Asks main service to start <b>something</b>.
* At this moment calling {@link #isActive()} should return {@code true}.
*
* @see #isActive()
* @see #requestInactive()
*/
void requestActive();
/**
* Asks main service to stop <b>something</b>.
* At this moment calling {@link #isActive()} should return {@code false}.
*
* @see #isActive()
* @see #requestActive()
*/
void requestInactive();
}
public Switch(@NonNull Context context, @NonNull Callback callback) {
mContext = context;
mCallback = callback;
}
/**
* Same as calling {@code getCallback().requestActive()}.
*
* @see Callback#requestActive()
* @see #getCallback()
*/
protected void requestActive() {
getCallback().requestActive();
}
/**
* Same as calling {@code getCallback().requestInactive()}.
*
* @see Callback#requestInactive()
* @see #getCallback()
*/
protected void requestInactive() {
getCallback().requestInactive();
}
@NonNull
public Callback getCallback() {
return mCallback;
}
/**
* @return {@link com.achep.acdisplay.services.activemode.ActiveModeService Service}'s context.
*/
@NonNull
public Context getContext() {
return mContext;
}
/**
* Called by the {@link SwitchService} when the service is created.
*/
public abstract void onCreate();
/**
* Called by the {@link SwitchService} to notify
* that this class is no longer used and is being removed.
* Here you should clean up any resources it holds
* (threads, registered receivers, etc) at this point.
*/
public abstract void onDestroy();
/**
* @return {@code true} if starting <b>something</b> is fine, {@code false} otherwise.
*/
public abstract boolean isActive();
final void create() {
mCreated = true;
onCreate();
}
final void destroy() {
onDestroy();
mCreated = false;
}
final boolean isCreated() {
return mCreated;
}
public abstract static class Optional extends Switch implements
ConfigBase.OnConfigChangedListener {
@NonNull
private Config mConfig;
private final boolean mOptionInverted;
@NonNull
private final ConfigBase.Option mOption;
@NonNull
private final String mOptionKey;
/**
* @param isOptionInverted {@code false} if enabled option means <i>actually</i> enabled
* feature, {@code true} if it's inversed
*/
public Optional(
@NonNull Context context,
@NonNull Callback callback,
@NonNull ConfigBase.Option option, boolean isOptionInverted) {
super(context, callback);
mConfig = Config.getInstance();
mOption = option;
mOptionKey = mOption.getKey(mConfig);
mOptionInverted = isOptionInverted;
}
/**
* {@inheritDoc}
*/
@Override
public void onCreate() {
mConfig.registerListener(this);
}
/**
* {@inheritDoc}
*/
@Override
public void onDestroy() {
mConfig.unregisterListener(this);
}
/**
* {@inheritDoc}
*/
@Override
public final boolean isActive() {
return !isFeatureEnabled() || isActiveInternal();
}
/**
* @see #isActive()
*/
public abstract boolean isActiveInternal();
public void requestActiveInternal() {
Check.getInstance().isTrue(isActive());
requestActive();
}
public void requestInactiveInternal() {
if (isFeatureEnabled()) {
Check.getInstance().isFalse(isActive());
requestInactive();
}
}
@Override
public void onConfigChanged(@NonNull ConfigBase configBase,
@NonNull String key,
@NonNull Object value) {
if (key.equals(mOptionKey)) {
if (isFeatureEnabled((boolean) value)) {
if (isActiveInternal()) {
requestActive();
} else {
requestInactive();
}
} else {
// If you've disabled the active mode, check the
// amount of notifications and probably stop
// listening.
requestActive();
}
}
}
private boolean isFeatureEnabled() {
return isFeatureEnabled((boolean) mOption.read(mConfig));
}
private boolean isFeatureEnabled(boolean on) {
return mOptionInverted != on;
}
}
}