package com.dtolabs.rundeck.core.authorization.providers;

import com.dtolabs.rundeck.core.authorization.Attribute;
import com.dtolabs.rundeck.core.utils.cache.FileCache;
import org.yaml.snakeyaml.Yaml;

import java.io.*;
import java.util.Date;
import java.util.Set;

/**
 * Created by greg on 7/17/15.
 */
public class YamlProvider {
    /**
     * Load policies from a source
     *
     * @param source source
     *
     * @return policies
     *
     * @throws IOException
     */
    public static YamlPolicyCollection policiesFromSource(final YamlSource source) throws IOException {
        return new YamlPolicyCollection(source);
    }

    /**
     * Load policies from a source
     *
     * @param source source
     * @param forcedContext Context to require for all policies parsed
     *
     * @return policies
     *
     * @throws IOException
     */
    public static YamlPolicyCollection policiesFromSource(final YamlSource source, final Set<Attribute> forcedContext)
            throws IOException
    {
        return new YamlPolicyCollection(source, forcedContext);
    }

    /**
     * Load policies from a file
     *
     * @param source source
     *
     * @return policies
     *
     * @throws IOException
     */
    public static YamlPolicyCollection policiesFromFile(final File source) throws IOException {
        return new YamlPolicyCollection(sourceFromFile(source));
    }

    public static CacheableYamlSource sourceFromFile(final File file) {
        return new CacheableYamlFileSource(file);
    }

    /**
     * Source from a stream
     *
     * @param identity identity
     * @param stream   stream
     * @param modified date the content was last modified, for caching purposes
     *
     * @return source
     */
    public static CacheableYamlSource sourceFromStream(
            final String identity,
            final InputStream stream,
            final Date modified
    )
    {
        return new CacheableYamlStreamSource(stream, identity, modified);
    }

    private static class CacheableYamlFileSource implements CacheableYamlSource {
        private final File file;
        FileInputStream fileInputStream;

        public CacheableYamlFileSource(final File file) {
            this.file = file;
        }

        @Override
        public Iterable<Object> loadAll(final Yaml yaml) throws IOException
        {
            if (null == fileInputStream) {
                fileInputStream = new FileInputStream(file);
            }
            return yaml.loadAll(fileInputStream);
        }

        @Override
        public String getIdentity() {
            return file.getAbsolutePath();
        }

        @Override
        public void close() throws IOException {
            if (null != fileInputStream) {
                fileInputStream.close();
            }
        }

        @Override
        public boolean isValid() {
            return file.exists();
        }

        @Override
        public Date getLastModified() {
            return new Date(file.lastModified());
        }

        @Override
        public boolean equals(final Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }

            final CacheableYamlFileSource that = (CacheableYamlFileSource) o;

            return file.equals(that.file);

        }

        @Override
        public int hashCode() {
            return file.hashCode();
        }
    }

    private static class CacheableYamlStreamSource implements CacheableYamlSource {
        private final InputStream stream;
        private final String identity;
        private final Date modified;

        public CacheableYamlStreamSource(final InputStream stream, final String identity, final Date modified) {
            this.stream = stream;
            this.identity = identity;
            this.modified = modified;
        }

        @Override
        public Iterable<Object> loadAll(final Yaml yaml) throws IOException {
            return yaml.loadAll(stream);
        }

        @Override
        public String getIdentity() {
            return identity;
        }

        @Override
        public void close() throws IOException {
            stream.close();
        }

        @Override
        public boolean isValid() {
            try {
                return null != stream && stream.available() > -1;
            } catch (IOException e) {
                return false;
            }
        }

        @Override
        public Date getLastModified() {
            return modified;
        }

        @Override
        public boolean equals(final Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }

            final CacheableYamlStreamSource that = (CacheableYamlStreamSource) o;

            return identity.equals(that.identity);

        }

        @Override
        public int hashCode() {
            return identity.hashCode();
        }
    }
}

@@ -1526,32 +1526,1074 @@
 e(file);%0A    %7D%0A%0A
+    /**%0A     * Source from a stream%0A     *%0A     * @param identity identity%0A     * @param content  yaml string%0A     * @param modified date the content was last modified, for caching purposes%0A     *%0A     * @return source%0A     */%0A    public static CacheableYamlSource sourceFromString(%0A            final String identity,%0A            final String content,%0A            final Date modified%0A    )%0A    %7B%0A        return new CacheableYamlSource() %7B%0A            @Override%0A            public boolean isValid() %7B%0A                return true;%0A            %7D%0A%0A            @Override%0A            public Date getLastModified() %7B%0A                return modified;%0A            %7D%0A%0A            @Override%0A            public String getIdentity() %7B%0A                return identity;%0A            %7D%0A%0A            @Override%0A            public Iterable%3CObject%3E loadAll(final Yaml yaml) throws IOException %7B%0A                return yaml.loadAll(content);%0A            %7D%0A%0A            @Override%0A            public void close() throws IOException %7B%0A%0A            %7D%0A        %7D;%0A    %7D%0A
     /**%0A     * S

Add String yaml source