// Path: node-extensions/sikuli-extension/src/main/java/io/sterodium/extensions/node/rmi/TargetFactory.java
// public class TargetFactory {
// 
//     private File folderToScan = new File(".");
// 
//     public void setImagePrefix(String imagePathPrefix) {
//         String imageFolder = !imagePathPrefix.endsWith("/") ? imagePathPrefix + "/" : imagePathPrefix;
//         this.folderToScan = new File(imageFolder);
//         checkState(folderToScan.exists(), "Folder %s does not exist", folderToScan.getAbsolutePath());
//         checkState(folderToScan.isDirectory(), "Folder %s is not a folder", folderToScan.getAbsolutePath());
//     }
// 
//     public ImageTarget createImageTarget(String imageFile) {
//         return new ImageTarget(findImageFile(imageFile));
//     }
// 
//     @VisibleForTesting
//     protected File findImageFile(String imageFile) {
//         File foundImageFile = findImageFile(folderToScan, imageFile);
//         // creating non existing file to avoid NPE
//         return foundImageFile == null ? new File(imageFile) : foundImageFile;
//     }
// 
//     private File findImageFile(File lookupFolder, String lookupTarget) {
//         // given file can contain sub-folders in its name
//         String[] paths = lookupTarget.split("[/\\\\]");
//         String[] foldersToFind = Arrays.copyOfRange(paths, 0, paths.length - 1);
// 
//         for (String folderToFind : foldersToFind) {
//             lookupFolder = findFolderRecursively(lookupFolder, folderToFind);
//             if (lookupFolder == null) {
//                 return null;
//             }
//         }
//         lookupTarget = paths[paths.length - 1];
// 
//         // finally searching for file name recursively
//         Collection<File> files = listFiles(lookupFolder, new NameFileFilter(lookupTarget), TRUE);
//         return files.isEmpty() ? null : files.iterator().next();
//     }
// 
//     private File findFolderRecursively(File folderToScan, final String folderToFind) {
//         // filtering out empty arguments
//         if (folderToFind.isEmpty()) {
//             return folderToScan;
//         }
// 
//         // collecting all the sub-folders recursively
//         Collection<File> foundFolders = listFilesAndDirs(folderToScan, DIRECTORY, TRUE);
// 
//         // filtering all the folders by folder name
//         foundFolders = filter(foundFolders, new Predicate<File>() {
//             @Override
//             public boolean apply(File file) {
//                 String fileName = file.getAbsolutePath();
//                 return fileName.endsWith("/" + folderToFind) || fileName.endsWith("\\" + folderToFind);
//             }
//         });
//         return foundFolders.isEmpty() ? null : foundFolders.iterator().next();
//     }
// 
// }


import io.sterodium.extensions.node.rmi.TargetFactory;
import io.sterodium.rmi.protocol.client.RemoteNavigator;
import org.sikuli.api.DesktopScreenRegion;
import org.sikuli.api.robot.Keyboard;
import org.sikuli.api.robot.Mouse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.datatransfer.Clipboard;
package io.sterodium.extensions.client;




/**
 * @author Mihails Volkovs mihails.volkovs@gmail.com
 *         Date: 24/09/2015
 */
@SuppressWarnings("UnusedDeclaration")
public final class SikuliExtensionClient {

    private static final Logger LOGGER = LoggerFactory
            .getLogger(SikuliExtensionClient.class);

    static final String SIKULI_EXTENSION_PATH = "/grid/admin/HubRequestsProxyingServlet/session/%s/SikuliExtensionServlet";

    private RemoteNavigator navigator;
    private FileExtensionClient fileExtensionClient;

    public SikuliExtensionClient(String host, int port, String sessionId) {
        navigator = new RemoteNavigator(host, port, String.format(SIKULI_EXTENSION_PATH, sessionId));
        fileExtensionClient = new FileExtensionClient(host, port, sessionId);
    }

    public Mouse getMouse() {
        return navigator.createProxy(Mouse.class, "mouse");
    }

// Path: node-extensions/sikuli-extension/src/main/java/io/sterodium/extensions/node/rmi/TargetFactory.java
// public class TargetFactory {
// 
//     private File folderToScan = new File(".");
// 
//     public void setImagePrefix(String imagePathPrefix) {
//         String imageFolder = !imagePathPrefix.endsWith("/") ? imagePathPrefix + "/" : imagePathPrefix;
//         this.folderToScan = new File(imageFolder);
//         checkState(folderToScan.exists(), "Folder %s does not exist", folderToScan.getAbsolutePath());
//         checkState(folderToScan.isDirectory(), "Folder %s is not a folder", folderToScan.getAbsolutePath());
//     }
// 
//     public ImageTarget createImageTarget(String imageFile) {
//         return new ImageTarget(findImageFile(imageFile));
//     }
// 
//     @VisibleForTesting
//     protected File findImageFile(String imageFile) {
//         File foundImageFile = findImageFile(folderToScan, imageFile);
//         // creating non existing file to avoid NPE
//         return foundImageFile == null ? new File(imageFile) : foundImageFile;
//     }
// 
//     private File findImageFile(File lookupFolder, String lookupTarget) {
//         // given file can contain sub-folders in its name
//         String[] paths = lookupTarget.split("[/\\\\]");
//         String[] foldersToFind = Arrays.copyOfRange(paths, 0, paths.length - 1);
// 
//         for (String folderToFind : foldersToFind) {
//             lookupFolder = findFolderRecursively(lookupFolder, folderToFind);
//             if (lookupFolder == null) {
//                 return null;
//             }
//         }
//         lookupTarget = paths[paths.length - 1];
// 
//         // finally searching for file name recursively
//         Collection<File> files = listFiles(lookupFolder, new NameFileFilter(lookupTarget), TRUE);
//         return files.isEmpty() ? null : files.iterator().next();
//     }
// 
//     private File findFolderRecursively(File folderToScan, final String folderToFind) {
//         // filtering out empty arguments
//         if (folderToFind.isEmpty()) {
//             return folderToScan;
//         }
// 
//         // collecting all the sub-folders recursively
//         Collection<File> foundFolders = listFilesAndDirs(folderToScan, DIRECTORY, TRUE);
// 
//         // filtering all the folders by folder name
//         foundFolders = filter(foundFolders, new Predicate<File>() {
//             @Override
//             public boolean apply(File file) {
//                 String fileName = file.getAbsolutePath();
//                 return fileName.endsWith("/" + folderToFind) || fileName.endsWith("\\" + folderToFind);
//             }
//         });
//         return foundFolders.isEmpty() ? null : foundFolders.iterator().next();
//     }
// 
// }


// Path: extension-clients/sikuli-extension-client/src/main/java/io/sterodium/extensions/client/SikuliExtensionClient.java
import io.sterodium.extensions.node.rmi.TargetFactory;
import io.sterodium.rmi.protocol.client.RemoteNavigator;
import org.sikuli.api.DesktopScreenRegion;
import org.sikuli.api.robot.Keyboard;
import org.sikuli.api.robot.Mouse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.datatransfer.Clipboard;

package io.sterodium.extensions.client;




/**
 * @author Mihails Volkovs mihails.volkovs@gmail.com
 *         Date: 24/09/2015
 */
@SuppressWarnings("UnusedDeclaration")
public final class SikuliExtensionClient {

    private static final Logger LOGGER = LoggerFactory
            .getLogger(SikuliExtensionClient.class);

    static final String SIKULI_EXTENSION_PATH = "/grid/admin/HubRequestsProxyingServlet/session/%s/SikuliExtensionServlet";

    private RemoteNavigator navigator;
    private FileExtensionClient fileExtensionClient;

    public SikuliExtensionClient(String host, int port, String sessionId) {
        navigator = new RemoteNavigator(host, port, String.format(SIKULI_EXTENSION_PATH, sessionId));
        fileExtensionClient = new FileExtensionClient(host, port, sessionId);
    }

    public Mouse getMouse() {
        return navigator.createProxy(Mouse.class, "mouse");
    }

    public Keyboard getKeyboard() {