// Path: src/main/java/com/github/xsavikx/androidscreencast/api/AndroidDeviceImpl.java
// @Singleton
// public final class AndroidDeviceImpl implements AndroidDevice {
// 
//     private final IDevice device;
// 
//     @Inject
//     public AndroidDeviceImpl(final IDevice device) {
//         this.device = device;
//     }
// 
//     @Override
//     public String executeCommand(final String cmd) {
//         log().debug("Executing command: `{}`.", cmd);
//         try (final ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
//             device.executeShellCommand(cmd, new OutputStreamShellOutputReceiver(bos));
//             final String result = new String(bos.toByteArray(), StandardCharsets.UTF_8);
//             log().debug("Command `{}` executed with result: `{}`.", cmd, result);
//             return result;
//         } catch (final Exception ex) {
//             log().error("Unable to execute command `{}`.", cmd, ex);
//             throw new ExecuteCommandException(cmd);
//         }
//     }
// 
//     @Override
//     public List<FileInfo> list(final String path) {
//         log().debug("Listing files under path: `{}`.", path);
//         try {
//             final String s = executeCommand("ls -l " + path);
//             final String[] entries = s.split("\r\n");
//             final List<FileInfo> fileInfos = new ArrayList<>();
//             for (final String entry : entries) {
//                 String[] data = entry.split(" ");
//                 if (data.length < 4)
//                     continue;
//                 String attributes = data[0];
//                 boolean directory = attributes.charAt(0) == 'd';
//                 String name = data[data.length - 1];
// 
//                 final FileInfo fi = new FileInfo();
//                 fi.attribs = attributes;
//                 fi.directory = directory;
//                 fi.name = name;
//                 fi.path = path;
//                 fi.device = this;
// 
//                 fileInfos.add(fi);
//             }
//             log().debug("Found `{}` files under path `{}`.", fileInfos.size(), path);
//             return fileInfos;
//         } catch (final Exception ex) {
//             log().error("Unable to list files under path `{}`.", path, ex);
//             throw new AndroidScreenCastRuntimeException(ex);
//         }
//     }
// 
//     @Override
//     public void openUrl(final String url) {
//         log().debug("Opening URL: `{}`.", url);
//         executeCommand("am start " + url);
//     }
// 
//     @Override
//     public void pullFile(final String remote, final File local) {
//         log().debug("Pulling remote file `{}` to the local destination: `{}`.", remote, local);
//         // ugly hack to call the method without FileEntry
//         try {
//             if (device.getSyncService() == null)
//                 throw new AndroidScreenCastRuntimeException("SyncService is null, ADB crashed ?");
//             device.getSyncService().pullFile(remote, local.getAbsolutePath(), SyncService.getNullProgressMonitor());
//             log().debug("Remote file `{}` pulled to the local destination: `{}`.", remote, local);
//         } catch (final Exception ex) {
//             log().error("Unable to pull remote file `{}` to the local destination: `{}`.", remote, local, ex);
//             throw new AndroidScreenCastRuntimeException(ex);
//         }
//     }
// 
//     @Override
//     public void pushFile(final File local, final String remote) {
//         log().debug("Pushing local file `{}` to the remote destination: `{}`.", local, remote);
//         try {
//             if (device.getSyncService() == null)
//                 throw new AndroidScreenCastRuntimeException("SyncService is null, ADB crashed ?");
//             device.getSyncService().pushFile(local.getAbsolutePath(), remote, SyncService.getNullProgressMonitor());
//             log().debug("Local file `{}` pushed to the remote destination: `{}`.", local, remote);
//         } catch (final Exception ex) {
//             log().error("Unable to push local file `{}` to the remote destination: `{}`.", local, remote, ex);
//             throw new AndroidScreenCastRuntimeException(ex);
//         }
//     }
// 
//     private enum LogSingleton {
//         INSTANCE;
// 
//         @SuppressWarnings({"NonSerializableFieldInSerializableClass", "ImmutableEnumChecker"})
//         private final Logger value = getLogger(AndroidDeviceImpl.class);
//     }
// 
//     private static Logger log() {
//         return LogSingleton.INSTANCE.value;
//     }
// }
// 
// Path: src/main/java/com/github/xsavikx/androidscreencast/exception/IORuntimeException.java
// public final class IORuntimeException extends AndroidScreenCastRuntimeException {
// 
//     public IORuntimeException(String message, IOException cause) {
//         super(message, cause);
//     }
// 
//     public IORuntimeException(IOException cause) {
//         super(cause);
//     }
// 
//     public IORuntimeException(String message, IOException cause, boolean enableSuppression, boolean writableStackTrace) {
//         super(message, cause, enableSuppression, writableStackTrace);
//     }
// }


import com.github.xsavikx.androidscreencast.api.AndroidDeviceImpl;
import com.github.xsavikx.androidscreencast.exception.IORuntimeException;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.io.File;
import java.io.IOException;
/*
 * Copyright 2020 Yurii Serhiichuk
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.github.xsavikx.androidscreencast.api.file;



@Singleton
public final class FileInfo {

    public AndroidDeviceImpl device;
    public String path;
    public String attribs;
    public boolean directory;
    public String name;

    @Inject
    public FileInfo() {
    }

    public File downloadTemporary() {
        try {
            File tempFile = File.createTempFile("android", name);
            device.pullFile(path + name, tempFile);
// Path: src/main/java/com/github/xsavikx/androidscreencast/api/AndroidDeviceImpl.java
// @Singleton
// public final class AndroidDeviceImpl implements AndroidDevice {
// 
//     private final IDevice device;
// 
//     @Inject
//     public AndroidDeviceImpl(final IDevice device) {
//         this.device = device;
//     }
// 
//     @Override
//     public String executeCommand(final String cmd) {
//         log().debug("Executing command: `{}`.", cmd);
//         try (final ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
//             device.executeShellCommand(cmd, new OutputStreamShellOutputReceiver(bos));
//             final String result = new String(bos.toByteArray(), StandardCharsets.UTF_8);
//             log().debug("Command `{}` executed with result: `{}`.", cmd, result);
//             return result;
//         } catch (final Exception ex) {
//             log().error("Unable to execute command `{}`.", cmd, ex);
//             throw new ExecuteCommandException(cmd);
//         }
//     }
// 
//     @Override
//     public List<FileInfo> list(final String path) {
//         log().debug("Listing files under path: `{}`.", path);
//         try {
//             final String s = executeCommand("ls -l " + path);
//             final String[] entries = s.split("\r\n");
//             final List<FileInfo> fileInfos = new ArrayList<>();
//             for (final String entry : entries) {
//                 String[] data = entry.split(" ");
//                 if (data.length < 4)
//                     continue;
//                 String attributes = data[0];
//                 boolean directory = attributes.charAt(0) == 'd';
//                 String name = data[data.length - 1];
// 
//                 final FileInfo fi = new FileInfo();
//                 fi.attribs = attributes;
//                 fi.directory = directory;
//                 fi.name = name;
//                 fi.path = path;
//                 fi.device = this;
// 
//                 fileInfos.add(fi);
//             }
//             log().debug("Found `{}` files under path `{}`.", fileInfos.size(), path);
//             return fileInfos;
//         } catch (final Exception ex) {
//             log().error("Unable to list files under path `{}`.", path, ex);
//             throw new AndroidScreenCastRuntimeException(ex);
//         }
//     }
// 
//     @Override
//     public void openUrl(final String url) {
//         log().debug("Opening URL: `{}`.", url);
//         executeCommand("am start " + url);
//     }
// 
//     @Override
//     public void pullFile(final String remote, final File local) {
//         log().debug("Pulling remote file `{}` to the local destination: `{}`.", remote, local);
//         // ugly hack to call the method without FileEntry
//         try {
//             if (device.getSyncService() == null)
//                 throw new AndroidScreenCastRuntimeException("SyncService is null, ADB crashed ?");
//             device.getSyncService().pullFile(remote, local.getAbsolutePath(), SyncService.getNullProgressMonitor());
//             log().debug("Remote file `{}` pulled to the local destination: `{}`.", remote, local);
//         } catch (final Exception ex) {
//             log().error("Unable to pull remote file `{}` to the local destination: `{}`.", remote, local, ex);
//             throw new AndroidScreenCastRuntimeException(ex);
//         }
//     }
// 
//     @Override
//     public void pushFile(final File local, final String remote) {
//         log().debug("Pushing local file `{}` to the remote destination: `{}`.", local, remote);
//         try {
//             if (device.getSyncService() == null)
//                 throw new AndroidScreenCastRuntimeException("SyncService is null, ADB crashed ?");
//             device.getSyncService().pushFile(local.getAbsolutePath(), remote, SyncService.getNullProgressMonitor());
//             log().debug("Local file `{}` pushed to the remote destination: `{}`.", local, remote);
//         } catch (final Exception ex) {
//             log().error("Unable to push local file `{}` to the remote destination: `{}`.", local, remote, ex);
//             throw new AndroidScreenCastRuntimeException(ex);
//         }
//     }
// 
//     private enum LogSingleton {
//         INSTANCE;
// 
//         @SuppressWarnings({"NonSerializableFieldInSerializableClass", "ImmutableEnumChecker"})
//         private final Logger value = getLogger(AndroidDeviceImpl.class);
//     }
// 
//     private static Logger log() {
//         return LogSingleton.INSTANCE.value;
//     }
// }
// 
// Path: src/main/java/com/github/xsavikx/androidscreencast/exception/IORuntimeException.java
// public final class IORuntimeException extends AndroidScreenCastRuntimeException {
// 
//     public IORuntimeException(String message, IOException cause) {
//         super(message, cause);
//     }
// 
//     public IORuntimeException(IOException cause) {
//         super(cause);
//     }
// 
//     public IORuntimeException(String message, IOException cause, boolean enableSuppression, boolean writableStackTrace) {
//         super(message, cause, enableSuppression, writableStackTrace);
//     }
// }


// Path: src/main/java/com/github/xsavikx/androidscreencast/api/file/FileInfo.java
import com.github.xsavikx.androidscreencast.api.AndroidDeviceImpl;
import com.github.xsavikx.androidscreencast.exception.IORuntimeException;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.io.File;
import java.io.IOException;

/*
 * Copyright 2020 Yurii Serhiichuk
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.github.xsavikx.androidscreencast.api.file;



@Singleton
public final class FileInfo {

    public AndroidDeviceImpl device;
    public String path;
    public String attribs;
    public boolean directory;
    public String name;

    @Inject
    public FileInfo() {
    }

    public File downloadTemporary() {
        try {
            File tempFile = File.createTempFile("android", name);
            device.pullFile(path + name, tempFile);
            tempFile.deleteOnExit();