/*
* Copyright (c) 2014-2016 Jan Strauß <jan[at]over9000.eu>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package eu.over9000.skadi.model;
import eu.over9000.skadi.io.PersistenceHandler;
import eu.over9000.skadi.remote.ChannelDataRetriever;
import eu.over9000.skadi.service.ChannelUpdateService;
import eu.over9000.skadi.ui.StatusBarWrapper;
import eu.over9000.skadi.util.StringUtil;
import javafx.beans.Observable;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.collections.ObservableMap;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class ChannelStore {
private final ObservableList<Channel> channels = FXCollections.observableArrayList(c -> new Observable[]{c.titleProperty(), c.nameProperty(), c.uptimeProperty(), c.onlineProperty(), c.viewerProperty(), c.gameProperty()});
private final ObservableMap<Channel, ChannelUpdateService> channelUpdater = FXCollections.observableHashMap();
public ChannelStore(final PersistenceHandler persistenceHandler, final StateContainer state) {
final List<Channel> emptyChannels = state.getChannels().stream().map(String::toLowerCase).map(Channel::new).collect(Collectors.toList());
channels.addListener((final ListChangeListener.Change<? extends Channel> c) -> {
boolean updateState = false;
while (c.next()) {
if (c.wasAdded()) {
updateState = true;
for (final Channel channel : c.getAddedSubList()) {
final ChannelUpdateService service = new ChannelUpdateService(channel);
service.start();
channelUpdater.put(channel, service);
}
} else if (c.wasRemoved()) {
updateState = true;
for (final Channel channel : c.getRemoved()) {
final ChannelUpdateService service = channelUpdater.remove(channel);
service.cancel();
}
}
}
if (updateState) {
final List<String> channelnames = getChannelNames();
if (channelnames.containsAll(state.getChannels()) && state.getChannels().containsAll(channelnames)) {
return;
}
state.getChannels().clear();
state.getChannels().addAll(channelnames);
persistenceHandler.saveState(state);
}
});
channels.addAll(emptyChannels);
}
public ObservableList<Channel> getChannels() {
return channels;
}
public List<String> getChannelNames() {
return channels.stream().flatMap(c -> Stream.of(c.getName())).sorted().collect(Collectors.toList());
}
private Channel buildDummyChannel(final String name) {
return new Channel(name);
}
public boolean addChannel(final String name, final StatusBarWrapper sb) {
if (!checkPattern(name)) {
sb.updateStatusText(name + " is no vaild channelname");
return false;
}
if (checkContains(name)) {
sb.updateStatusText("channel " + name + " is already added");
return false;
}
if (!checkExists(name)) {
sb.updateStatusText("channel " + name + " does not exist");
return false;
}
final Channel newChannel = buildDummyChannel(name);
channels.add(newChannel);
sb.updateStatusText("added channel " + name);
return true;
}
public void addChannels(final Collection<String> result, final StatusBarWrapper sb) {
final Set<Channel> dummys = new HashSet<>();
result.forEach(c -> {
if (checkPattern(c) && !checkContains(c)) {
dummys.add(buildDummyChannel(c));
}
});
channels.addAll(dummys);
sb.updateStatusText("added " + dummys.size() + " channels");
}
private boolean checkPattern(final String channel) {
return Pattern.matches(StringUtil.USERNAME_REGEX, channel);
}
private boolean checkContains(final String channel) {
return StringUtil.containsIgnoreCase(getChannelNames(), channel);
}
private boolean checkExists(final String channel) {
return ChannelDataRetriever.checkIfChannelExists(channel);
}
}