// 
// Decompiled by Procyon v0.6.0
// 

package org.jline.builtins;

import java.io.FilterInputStream;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.util.stream.Stream;
import java.nio.file.Files;
import java.io.File;
import java.util.Objects;
import java.net.URL;
import java.io.IOException;
import java.io.InputStream;

public interface Source
{
    String getName();
    
    InputStream read() throws IOException;
    
    Long lines();
    
    public static class URLSource implements Source
    {
        final URL url;
        final String name;
        
        public URLSource(final URL url, final String name) {
            this.url = Objects.requireNonNull(url);
            this.name = name;
        }
        
        @Override
        public String getName() {
            return this.name;
        }
        
        @Override
        public InputStream read() throws IOException {
            return this.url.openStream();
        }
        
        @Override
        public Long lines() {
            Long out = null;
            try (final Stream<String> lines = Files.lines(new File(this.url.toURI()).toPath())) {
                out = lines.count();
            }
            catch (final Exception ex) {}
            return out;
        }
    }
    
    public static class PathSource implements Source
    {
        final Path path;
        final String name;
        
        public PathSource(final File file, final String name) {
            this(Objects.requireNonNull(file).toPath(), name);
        }
        
        public PathSource(final Path path, final String name) {
            this.path = Objects.requireNonNull(path);
            this.name = name;
        }
        
        @Override
        public String getName() {
            return this.name;
        }
        
        @Override
        public InputStream read() throws IOException {
            return Files.newInputStream(this.path, new OpenOption[0]);
        }
        
        @Override
        public Long lines() {
            Long out = null;
            try (final Stream<String> lines = Files.lines(this.path)) {
                out = lines.count();
            }
            catch (final Exception ex) {}
            return out;
        }
    }
    
    public static class InputStreamSource implements Source
    {
        final InputStream in;
        final String name;
        
        public InputStreamSource(final InputStream in, final boolean close, final String name) {
            Objects.requireNonNull(in);
            if (close) {
                this.in = in;
            }
            else {
                this.in = new FilterInputStream(in) {
                    @Override
                    public void close() throws IOException {
                    }
                };
            }
            if (this.in.markSupported()) {
                this.in.mark(Integer.MAX_VALUE);
            }
            this.name = name;
        }
        
        @Override
        public String getName() {
            return this.name;
        }
        
        @Override
        public InputStream read() throws IOException {
            if (this.in.markSupported()) {
                this.in.reset();
            }
            return this.in;
        }
        
        @Override
        public Long lines() {
            return null;
        }
    }
    
    public static class StdInSource extends InputStreamSource
    {
        public StdInSource() {
            this(System.in);
        }
        
        public StdInSource(final InputStream in) {
            super(in, false, null);
        }
    }
    
    public static class ResourceSource implements Source
    {
        final String resource;
        final String name;
        
        public ResourceSource(final String resource) {
            this(resource, resource);
        }
        
        public ResourceSource(final String resource, final String name) {
            this.resource = Objects.requireNonNull(resource);
            this.name = name;
        }
        
        @Override
        public String getName() {
            return this.name;
        }
        
        @Override
        public InputStream read() throws IOException {
            return this.getClass().getResourceAsStream(this.resource);
        }
        
        @Override
        public Long lines() {
            return null;
        }
    }
}
