/**
* Copyright 2014 Comcast Cable Communications Management, LLC
*
* This file is part of CATS.
*
* CATS 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 3 of the License, or
* (at your option) any later version.
*
* CATS 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 CATS. If not, see <http://www.gnu.org/licenses/>.
*/
package com.comcast.cats.provider;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.comcast.cats.RemoteCommand;
import com.comcast.cats.RemoteLayout;
import com.comcast.cats.RemoteCommandShortcutResolver;
import com.comcast.cats.info.RemoteCommandSequence;
import com.comcast.cats.keymanager.domain.Remote;
import com.comcast.cats.service.IRService;
public class RemoteProviderServiceImpl implements RemoteProvider {
/**
*
*/
private static final long serialVersionUID = -4973165057686246850L;
private static final int DELAY_BETWEEN_KEYS=100;
public static final Logger logger = LoggerFactory.getLogger(RemoteProvider.class);
private Integer delay=0;
private Object parent;
private URI irPath;
private String remoteType;
private IRService irService;
private boolean autoTuneEnabled = false;
public RemoteProviderServiceImpl(IRService irService, URI irPath, String remoteType) {
this.irService = irService;
assignParams(irPath, remoteType);
}
private boolean mustDelay() {
return (delay > 0);
}
private boolean sleepOnTrue(boolean condition) {
if(condition && mustDelay()) {
sleep();
}
return condition;
}
protected void verifyDelay(int delay) {
if(delay < 0 || delay > MAX_DELAY) {
throw new IllegalArgumentException("Remote delay must be 0 >= delay <= " + MAX_DELAY);
}
}
protected void sleep(int delay) {
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
logger.warn("Interrupted during sleep operation.");
}
}
protected void sleep() {
sleep(this.delay);
}
/**
* Helper method to assign parameters common for all constructors.
* @param irPath
* @param remoteType
*/
private void assignParams(URI irPath, String remoteType) {
this.irPath = irPath;
this.remoteType = remoteType;
}
@Override
public URI getRemoteLocator() {
return irPath;
}
@Override
public String getRemoteType() {
return remoteType;
}
@Override
public void setRemoteType(String remoteType) {
this.remoteType = remoteType;
}
@Override
public List<RemoteLayout> getValidKeys() {
return irService.getRemoteLayout(remoteType);
}
@Override
public boolean isAutoTuneEnabled() {
return autoTuneEnabled;
}
@Override
public void setAutoTuneEnabled(boolean autoTuneEnabled) {
this.autoTuneEnabled = autoTuneEnabled;
}
@Override
public boolean pressKey(RemoteCommand command) {
return sleepOnTrue(irService.pressKey(irPath, remoteType, command));
}
@Override
public boolean pressKey(RemoteCommand command, Integer delay) {
verifyDelay(delay);
boolean rtn = irService.pressKey(irPath, remoteType, command);
sleep(delay);
return rtn;
}
@Override
public boolean pressKeyAndHold(RemoteCommand command, Integer count) {
return sleepOnTrue(irService.pressKeyAndHold(irPath, remoteType, command, count));
}
@Override
public boolean pressKeys(List<RemoteCommand> commands) {
return sleepOnTrue(irService.pressKeys(irPath, remoteType, commands, delay));
}
@Override
public boolean pressKeys(List<RemoteCommand> commands, Integer delay) {
return sleepOnTrue(irService.pressKeys(irPath, remoteType, commands, delay));
}
@Override
public boolean tune(String channel) {
verifyChannelNumber( channel );
return sleepOnTrue(irService.tune(irPath, remoteType, channel, autoTuneEnabled, DELAY_BETWEEN_KEYS));
}
public void setParent(Object parent) {
this.parent = parent;
}
@Override
public Object getParent() {
return parent;
}
@Override
public void setDelay(Integer delay) {
verifyDelay(delay);
this.delay = delay;
}
@Override
public Integer getDelay() {
return delay;
}
@Override
public boolean enterCustomKeySequence(List<RemoteCommand> commands,
List<Integer> repeatCount, List<Integer> delay) {
return sleepOnTrue(irService.enterCustomKeySequence(irPath, remoteType, commands,repeatCount, delay));
}
@Override
public boolean enterRemoteCommandSequence(List<RemoteCommandSequence> commands) {
return sleepOnTrue(irService.enterRemoteCommandSequence(irPath, remoteType, commands));
}
@Override
public boolean pressKey( RemoteCommand[] commands )
{
return pressKeys( Arrays.asList( commands ) );
}
@Override
public boolean pressKey( Integer count, RemoteCommand command )
{
boolean toReturn = true;
for(int i = 0; i < count; i++)
{
toReturn = pressKey( command );
if( false == toReturn )
{
break;
}
}
return toReturn;
}
@Override
public boolean pressKey( Integer count, RemoteCommand command, Integer delay )
{
verifyDelay(delay);
boolean toReturn = true;
for( int i = 0; i < count; i++)
{
toReturn = pressKey( command );
if( false == toReturn )
{
break;
}
sleep( delay );
}
return toReturn;
}
@Override
public boolean pressKey( Integer count, Integer delay, RemoteCommand[] commands )
{
verifyDelay(delay);
boolean toReturn = true;
for( int i = 0; i < count; i++ )
{
toReturn = pressKeys( Arrays.asList( commands ), delay );
if(false == toReturn)
{
break;
}
sleep( delay );
}
return toReturn;
}
@Override
public boolean pressKey( Integer command )
{
return pressKey( RemoteCommand.parse( command ) );
}
@Override
public boolean tune( Integer channel )
{
return tune( channel.toString() );
}
@Override
public boolean sendText( String text )
{
logger.info( "Text Message is sent" );
return irService.sendText( irPath, remoteType, text );
}
private void verifyChannelNumber( String channel )
{
Pattern CHANNEL_VALIDATOR = Pattern.compile( "\\d{1,4}" );
if( !CHANNEL_VALIDATOR.matcher( channel ).matches() )
{
throw new IllegalArgumentException("Invalid channel number: " + channel);
}
}
@Override
public List<String> getAllRemoteTypes(){
List<String> remoteTypes = new ArrayList< String >();
List<Remote> remotes = irService.getRemotes();
if(remotes != null){
for(Remote remote: remotes){
remoteTypes.add( remote.getName() );
}
}
return remoteTypes;
}
@Override
public boolean performShorthandCommandSequence(String text) {
return performShorthandCommandSequence(text,DELAY_BETWEEN_KEYS);
}
@Override
public boolean performShorthandCommandSequence(String text, Integer delay) {
boolean returnVal = false ;
if ( !(null == text || text.isEmpty()) )
{
char[] chars = text.toCharArray();
List< RemoteCommand > commands = new ArrayList< RemoteCommand >();
for ( char character : chars )
{
commands.add( RemoteCommandShortcutResolver.resolveRemoteCommand(character) );
}
logger.info( "sendText : commands:" + commands );
returnVal = pressKeys( commands,delay );
}
return returnVal;
}
}