package com.kuxhausen.huemore.net;
import android.app.Service;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.util.Pair;
import com.kuxhausen.huemore.net.dev.DevLogger;
import com.kuxhausen.huemore.net.dev.IpcMaster;
import com.kuxhausen.huemore.net.hue.HubConnection;
import com.kuxhausen.huemore.net.lifx.LifxConnection;
import com.kuxhausen.huemore.net.lifx.LifxManager;
import com.kuxhausen.huemore.persistence.Definitions.NetConnectionColumns;
import com.kuxhausen.huemore.state.Group;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class DeviceManager {
private ArrayList<Connection> mConnections;
private Service mContext;
private Group selectedGroup;
private ArrayList<OnConnectionStatusChangedListener> connectionListeners =
new ArrayList<OnConnectionStatusChangedListener>();
public ArrayList<OnStateChangedListener> brightnessListeners =
new ArrayList<OnStateChangedListener>();
public ArrayList<OnStateChangedListener> stateListeners = new ArrayList<OnStateChangedListener>();
private HashMap<Long, NetworkBulb> bulbMap;
private MyObserver mConnectionObserver;
private LifxManager mLifxManager;
private ArrayList<Pair<Group, BrightnessManager>>
mBrightnessManagers =
new ArrayList<Pair<Group, BrightnessManager>>();
// Prototype DeviceManager replacement, isolates lighting drivers into separate processes
private IpcMaster mIpcMaster;
public DeviceManager(Service c) {
mContext = c;
mConnectionObserver = new MyObserver(new Handler(Looper.getMainLooper()));
mContext.getContentResolver().registerContentObserver(NetConnectionColumns.URI, true,
mConnectionObserver);
if (DevLogger.NET_DEBUG) {
mIpcMaster = new IpcMaster(mContext);
}
loadEverythingFromDatabase();
}
private void loadEverythingFromDatabase() {
destroyManagers();
{ // load all connections from the database
mConnections = new ArrayList<Connection>();
//load any hue connections
mConnections.addAll(HubConnection.loadHubConnections(mContext, this));
//load any lifx connections
List<LifxConnection> lifxConnections = LifxManager.loadConnections(mContext, this);
if (!lifxConnections.isEmpty()) {
mLifxManager = new LifxManager();
mLifxManager.onCreate(mContext, this, lifxConnections);
mConnections.addAll(lifxConnections);
}
}
// load all network bulbs from the connections
bulbMap = new HashMap<Long, NetworkBulb>();
for (Connection con : mConnections) {
for (NetworkBulb bulb : con.getBulbs()) {
bulbMap.put(bulb.getBaseId(), bulb);
}
}
onBulbsListChanged();
}
public void destroyManagers() {
if (mLifxManager != null) {
mLifxManager.onDestroy();
mLifxManager = null;
}
mBrightnessManagers.clear();
}
public void onDestroy() {
destroyManagers();
mContext.getContentResolver().unregisterContentObserver(mConnectionObserver);
for (Connection c : mConnections) {
c.onDestroy();
}
if (DevLogger.NET_DEBUG) {
mIpcMaster.onDestroy();
mIpcMaster = null;
}
}
public Group getSelectedGroup() {
return selectedGroup;
}
public void onGroupSelected(Group group, Integer optionalBri) {
selectedGroup = group;
// TODO
}
public BrightnessManager obtainBrightnessManager(Group g) {
assert g != null;
//if a manager already exists for this group, return it
for (Pair<Group, BrightnessManager> pair : mBrightnessManagers) {
if (pair.first.equals(g)) {
return pair.second;
}
}
//else eliminate any conflicting managers
for (int i = 0; i < mBrightnessManagers.size(); i++) {
if (mBrightnessManagers.get(i).first.conflictsWith(g)) {
mBrightnessManagers.remove(i);
i--;
}
}
//and create a new manager
ArrayList<NetworkBulb> networkBulbs = new ArrayList<NetworkBulb>();
for (long id : g.getNetworkBulbDatabaseIds()) {
if (bulbMap.containsKey(id)) {
networkBulbs.add(bulbMap.get(id));
}
}
BrightnessManager newManager = new BrightnessManager(networkBulbs);
mBrightnessManagers.add(new Pair<Group, BrightnessManager>(g, newManager));
return newManager;
}
/**
* if a BrightnessManager is assigned to that group, return it else return null
*/
public BrightnessManager peekBrightnessManager(Group g) {
//if a manager exists for this group, return it
for (Pair<Group, BrightnessManager> pair : mBrightnessManagers) {
if (pair.first.equals(g)) {
return pair.second;
}
}
return null;
}
public ArrayList<Connection> getConnections() {
return mConnections;
}
public void addOnConnectionStatusChangedListener(OnConnectionStatusChangedListener l) {
connectionListeners.add(l);
}
public void removeOnConnectionStatusChangedListener(OnConnectionStatusChangedListener l) {
connectionListeners.remove(l);
}
public void onConnectionChanged() {
for (OnConnectionStatusChangedListener l : connectionListeners) {
l.onConnectionStatusChanged();
}
}
public interface OnStateChangedListener {
public void onStateChanged();
}
/**
* announce state changes to any listeners *
*/
public void onStateChanged() {
// only send brightnessListeners brightness state changes
for (OnStateChangedListener l : brightnessListeners) {
l.onStateChanged();
}
for (OnStateChangedListener l : stateListeners) {
l.onStateChanged();
}
}
public void registerStateListener(OnStateChangedListener l) {
stateListeners.add(l);
}
public void removeStateListener(OnStateChangedListener l) {
stateListeners.remove(l);
}
public void registerBrightnessListener(OnStateChangedListener l) {
brightnessListeners.add(l);
l.onStateChanged();
}
public void removeBrightnessListener(OnStateChangedListener l) {
brightnessListeners.remove(l);
}
public void onBulbsListChanged() {
bulbMap.clear();
for (Connection con : mConnections) {
ArrayList<NetworkBulb> conBulbs = con.getBulbs();
for (NetworkBulb bulb : conBulbs) {
bulbMap.put(bulb.getBaseId(), bulb);
}
}
}
public NetworkBulb getNetworkBulb(Long bulbDeviceId) {
return bulbMap.get(bulbDeviceId);
}
class MyObserver extends ContentObserver {
public MyObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange) {
this.onChange(selfChange, null);
}
@Override
public void onChange(boolean selfChange, Uri uri) {
loadEverythingFromDatabase();
}
}
/**
* Safely deletes references to connection's bulbs & connection, then deletes from database
*
* @param selected connection to delete
*/
public void delete(Connection selected) {
// TODO Auto-generated method stub
for (NetworkBulb nb : selected.getBulbs()) {
bulbMap.remove(nb.getBaseId());
}
this.mConnections.remove(selected);
selected.delete();
this.onConnectionChanged();
}
}