package li.klass.fhem.service.device;
import android.content.Context;
import android.support.annotation.NonNull;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Arrays;
import java.util.List;
import javax.inject.Inject;
import li.klass.fhem.domain.log.ConcernsDevicePredicate;
import li.klass.fhem.service.graph.gplot.GPlotDefinition;
import li.klass.fhem.service.graph.gplot.GPlotHolder;
import li.klass.fhem.service.graph.gplot.SvgGraphDefinition;
import li.klass.fhem.service.room.RoomListService;
import li.klass.fhem.service.room.xmllist.XmlListDevice;
import static com.google.common.collect.FluentIterable.from;
import static li.klass.fhem.service.room.xmllist.XmlListDevice.hasName;
public class GraphDefinitionsForDeviceService {
private final RoomListService roomListService;
private final GPlotHolder gPlotHolder;
private static final Logger LOGGER = LoggerFactory.getLogger(GraphDefinitionsForDeviceService.class);
@Inject
GraphDefinitionsForDeviceService(RoomListService roomListService, GPlotHolder gPlotHolder) {
this.roomListService = roomListService;
this.gPlotHolder = gPlotHolder;
}
public ImmutableSet<SvgGraphDefinition> graphDefinitionsFor(Context context, XmlListDevice device, Optional<String> connectionId) {
final ImmutableSet<XmlListDevice> allDevices = roomListService.getAllRoomsDeviceList(connectionId, context)
.getAllDevicesAsXmllistDevice();
LOGGER.info("graphDefinitionsFor(name={},connection={})", device.getName(), connectionId.or("--"));
ImmutableSet<SvgGraphDefinition> devices = from(allDevices)
.filter(XmlListDevice.hasType("SVG"))
.filter(hasConcerningLogDevice(allDevices, device))
.filter(gplotDefinitionExists(allDevices))
.transform(toGraphDefinition(allDevices)).toSet();
for (SvgGraphDefinition svgGraphDefinition : devices) {
LOGGER.info("graphDefinitionsFor(name={},connection={}) - found SVG with name {}", device.getName(), connectionId.or("--"), svgGraphDefinition.getName());
}
return devices;
}
@NonNull
private Function<XmlListDevice, SvgGraphDefinition> toGraphDefinition(final ImmutableSet<XmlListDevice> allDevices) {
return new Function<XmlListDevice, SvgGraphDefinition>() {
@Override
public SvgGraphDefinition apply(XmlListDevice svgDevice) {
String logDeviceName = svgDevice.getInternal("LOGDEVICE").get();
String gplotFileName = svgDevice.getInternal("GPLOTFILE").get();
GPlotDefinition gPlotDefinition = gPlotHolder.definitionFor(gplotFileName, isConfigDb(allDevices)).get();
List<String> labels = Arrays.asList(svgDevice.getAttribute("label")
.or("").replaceAll("\"", "").split(","));
String title = svgDevice.getAttribute("title").or("");
List<String> plotfunction = Arrays.asList(svgDevice.getAttribute("plotfunction").or("").trim().split(" "));
return new SvgGraphDefinition(svgDevice.getName(), gPlotDefinition, logDeviceName, labels, title, plotfunction);
}
};
}
@NonNull
private Predicate<XmlListDevice> gplotDefinitionExists(final ImmutableSet<XmlListDevice> allDevices) {
return new Predicate<XmlListDevice>() {
@Override
public boolean apply(XmlListDevice input) {
if (input == null) {
return false;
}
Optional<String> gplotFileName = input.getInternal("GPLOTFILE");
return gplotFileName.isPresent()
&& gPlotHolder.definitionFor(gplotFileName.get(), isConfigDb(allDevices)).isPresent();
}
};
}
@NonNull
private Predicate<XmlListDevice> hasConcerningLogDevice(final ImmutableSet<XmlListDevice> allDevices, final XmlListDevice inputDevice) {
return new Predicate<XmlListDevice>() {
@Override
public boolean apply(XmlListDevice svgDevice) {
if (svgDevice == null) {
return false;
}
final Optional<String> logDeviceName = svgDevice.getInternal("LOGDEVICE");
if (!logDeviceName.isPresent()) {
return false;
}
Optional<XmlListDevice> logDevice = from(allDevices)
.firstMatch(hasName(logDeviceName.get()));
if (!logDevice.isPresent()) {
return false;
}
Optional<String> logDeviceRegexp = logDevice.get().getInternal("REGEXP");
return logDeviceRegexp.isPresent() &&
ConcernsDevicePredicate.forPattern(logDeviceRegexp.get()).apply(inputDevice);
}
};
}
private boolean isConfigDb(ImmutableSet<XmlListDevice> allDevices) {
return from(allDevices)
.anyMatch(new Predicate<XmlListDevice>() {
@Override
public boolean apply(XmlListDevice input) {
return input != null && "configDB".equals(input.getAttribute("configfile").orNull());
}
});
}
}