/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.felix.utils.properties;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.net.URL;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static org.apache.felix.utils.properties.InterpolationHelper.substVars;

/**
 * <p>
 * Map to load / store / update untyped or typed properties.
 * The map is untyped if all properties are strings.
 * When this is the case, the properties are stored without
 * any encoding, else all properties are encoded using
 * the {@link ConfigurationHandler}.
 * </p>
 *
 * @author gnodet
 */
public class TypedProperties extends AbstractMap<String, Object> {

    public static final String ENV_PREFIX = "env:";

    private final Properties storage;
    private final SubstitutionCallback callback;
    private final boolean substitute;

    public TypedProperties() {
        this(null, true);
    }

    public TypedProperties(boolean substitute) {
        this(null, substitute);
    }

    public TypedProperties(SubstitutionCallback callback) {
        this(callback, true);
    }

    public TypedProperties(SubstitutionCallback callback, boolean substitute) {
        this.storage = new Properties(false);
        this.callback = callback;
        this.substitute = substitute;
    }

    public void load(File location) throws IOException {
        InputStream is = new FileInputStream(location);
        try {
            load(is);
        } finally {
            is.close();
        }
    }

    public void load(URL location) throws IOException {
        InputStream is = location.openStream();
        try {
            load(is);
        } finally {
            is.close();
        }
    }

    public void load(InputStream is) throws IOException {
        load(new InputStreamReader(is, Properties.DEFAULT_ENCODING));
    }

    public void load(Reader reader) throws IOException {
        storage.loadLayout(reader, true);
        substitute(callback);
    }

    public void save(File location) throws IOException {
        storage.save(location);
    }

    public void save(OutputStream os) throws IOException {
        storage.save(os);
    }

    public void save(Writer writer) throws IOException {
        storage.save(writer);
    }

    /**
     * Store a properties into a output stream, preserving comments, special character, etc.
     * This method is mainly to be compatible with the java.util.Properties class.
     *
     * @param os an output stream.
     * @param comment this parameter is ignored as this Properties
     * @throws IOException If storing fails
     */
    public void store(OutputStream os, String comment) throws IOException {
        storage.store(os, comment);
    }

    @Override
    public Set<Entry<String, Object>> entrySet() {
        return new AbstractSet<Entry<String, Object>>() {
            @Override
            public Iterator<Entry<String, Object>> iterator() {
                return new Iterator<Entry<String, Object>>() {
                    final Iterator<String> keyIterator = storage.keySet().iterator();
                    public boolean hasNext() {
                        return keyIterator.hasNext();
                    }
                    public Entry<String, Object> next() {
                        final String key = keyIterator.next();
                        return new Entry<String, Object>() {
                            public String getKey() {
                                return key;
                            }
                            public Object getValue() {
                                return TypedProperties.this.get(key);
                            }
                            public Object setValue(Object value) {
                                return TypedProperties.this.put(key, value);
                            }
                        };
                    }
                    public void remove() {
                        keyIterator.remove();
                    }
                };
            }

            @Override
            public int size() {
                return storage.size();
            }
        };
    }

    @Override
    public Object put(String key, Object value) {
        if (value instanceof String && !storage.typed) {
            return storage.put(key, (String) value);
        } else {
            ensureTyped();
            String old = storage.put(key, convertToString(value));
            return old != null ? convertFromString(old) : null;
        }
    }

    @Override
    public Object get(Object key) {
        String v = storage.get(key);
        return storage.typed && v != null ? convertFromString(v) : v;
    }

    public Object put(String key, List<String> commentLines, Object value) {
        if (value instanceof String && !storage.typed) {
            return storage.put(key, commentLines, (String) value);
        } else {
            ensureTyped();
            return put(key, commentLines, Arrays.asList(convertToString(value).split("\n")));
        }
    }

    public Object put(String key, String comment, Object value) {
        return put(key, Collections.singletonList(comment), value);
    }

    public Object put(String key, List<String> commentLines, List<String> valueLines) {
        String old = storage.put(key, commentLines, valueLines);
        return old != null ? storage.typed ? convertFromString(old) : old : null;
    }

    private void ensureTyped() {
        if (!storage.typed) {
            storage.typed = true;
            Set<String> keys = new HashSet<String>(storage.keySet());
            for (String key : keys) {
                storage.put(key,
                            storage.getComments(key),
                            Arrays.asList(convertToString(storage.get(key)).split("\n")));
            }
        }
    }

    public boolean update(Map<String, Object> props) {
        TypedProperties properties;
        if (props instanceof TypedProperties) {
            properties = (TypedProperties) props;
        } else {
            properties = new TypedProperties();
            for (Entry<String, Object> e : props.entrySet()) {
                properties.put(e.getKey(), e.getValue());
            }
        }
        return update(properties);
    }

    public boolean update(TypedProperties properties) {
        return storage.update(properties.storage);
    }

    public List<String> getRaw(String key) {
        return storage.getRaw(key);
    }

    public List<String> getComments(String key) {
        return storage.getComments(key);
    }

    @Override
    public Object remove(Object key) {
        return storage.remove(key);
    }

    @Override
    public void clear() {
        storage.clear();
    }

    /**
     * Return the comment header.
     *
     * @return the comment header
     */
    public List<String> getHeader()
    {
        return storage.getHeader();
    }

    /**
     * Set the comment header.
     *
     * @param header the header to use
     */
    public void setHeader(List<String> header)
    {
        storage.setHeader(header);
    }

    /**
     * Return the comment footer.
     *
     * @return the comment footer
     */
    public List<String> getFooter()
    {
        return storage.getFooter();
    }

    /**
     * Set the comment footer.
     *
     * @param footer the footer to use
     */
    public void setFooter(List<String> footer)
    {
        storage.setFooter(footer);
    }

    public void substitute(final SubstitutionCallback cb) {
        if (!substitute) {
            return;
        }
        final SubstitutionCallback callback = cb != null ? cb  : new SubstitutionCallback() {
            public String getValue(String name, String key, String value) {
                if (value.startsWith(ENV_PREFIX))
                {
                    return System.getenv(value.substring(ENV_PREFIX.length()));
                }
                else
                {
                    return System.getProperty(value);
                }
            }
        }; //wrap(new BundleContextSubstitutionCallback(null));
        Map<String, TypedProperties> props = Collections.singletonMap("root", this);
        substitute(props, prepare(props), callback, true);
    }

    private static SubstitutionCallback wrap(final InterpolationHelper.SubstitutionCallback cb) {
        return new SubstitutionCallback() {
            public String getValue(String name, String key, String value) {
                return cb.getValue(value);
            }
        };
    }

    public interface SubstitutionCallback {

        String getValue(String name, String key, String value);

    }

    public static Map<String, Map<String, String>> prepare(Map<String, TypedProperties> properties) {
        Map<String, Map<String, String>> dynamic = new HashMap<String, Map<String, String>>();
        for (Map.Entry<String, TypedProperties> entry : properties.entrySet()) {
            String name = entry.getKey();
            dynamic.put(name, new DynamicMap(name, entry.getValue().storage));
        }
        return dynamic;
    }

    public static void substitute(Map<String, TypedProperties> properties,
                                  Map<String, Map<String, String>> dynamic,
                                  SubstitutionCallback callback,
                                  boolean finalSubstitution) {
        for (Map<String, String> map : dynamic.values()) {
            ((DynamicMap) map).init(callback, finalSubstitution);
        }
        for (Map.Entry<String, TypedProperties> entry : properties.entrySet()) {
            entry.getValue().storage.putAllSubstituted(dynamic.get(entry.getKey()));
        }
    }

    private static String convertToString(Object value) {
        try {
            return ConfigurationHandler.write(value);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private static Object convertFromString(String value) {
        try {
            return ConfigurationHandler.read(value);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private static class DynamicMap extends AbstractMap<String, String> {
        private final String name;
        private final Properties storage;
        private final Map<String, String> computed;
        private final Map<String, String> cycles;
        private SubstitutionCallback callback;
        private boolean finalSubstitution;

        public DynamicMap(String name, Properties storage) {
            this.name = name;
            this.storage = storage;
            this.computed = new HashMap<String, String>();
            this.cycles = new HashMap<String, String>();
        }

        public void init(SubstitutionCallback callback, boolean finalSubstitution) {
            this.callback = callback;
            this.finalSubstitution = finalSubstitution;
        }

        @Override
        public Set<Entry<String, String>> entrySet() {
            return new AbstractSet<Entry<String, String>>() {
                @Override
                public Iterator<Entry<String, String>> iterator() {
                    final Iterator<String> iterator = storage.keySet().iterator();
                    return new Iterator<Entry<String, String>>() {
                        public boolean hasNext() {
                            return iterator.hasNext();
                        }
                        public Entry<String, String> next() {
                            final String key = iterator.next();
                            return new Entry<String, String>() {
                                public String getKey() {
                                    return key;
                                }
                                public String getValue() {
                                    String v = computed.get(key);
                                    if (v == null) {
                                        v = compute(key);
//                                        computed.put(key, v);
                                    }
                                    return v;
                                }
                                public String setValue(String value) {
                                    throw new UnsupportedOperationException();
                                }
                            };
                        }
                        public void remove() {
                            throw new UnsupportedOperationException();
                        }
                    };
                }

                @Override
                public int size() {
                    return storage.size();
                }
            };
        }

        private String compute(final String key) {
            InterpolationHelper.SubstitutionCallback wrapper = new InterpolationHelper.SubstitutionCallback() {
                public String getValue(String value) {
                    if (finalSubstitution) {
                        String str = DynamicMap.this.get(value);
                        if (str != null) {
                            if (storage.typed) {
                                boolean mult;
                                boolean hasType;
                                char t = str.charAt(0);
                                if (t == '[' || t == '(') {
                                    mult = true;
                                    hasType = false;
                                } else if (t == '"') {
                                    mult = false;
                                    hasType = false;
                                } else {
                                    t = str.charAt(1);
                                    mult = t == '[' || t == '(';
                                    hasType = true;
                                }
                                if (mult) {
                                    throw new IllegalArgumentException("Can't substitute from a collection/array value: " + value);
                                }
                                return (String) convertFromString(hasType ? str.substring(1) : str);
                            } else {
                                return str;
                            }
                        }
                    }
                    return callback.getValue(name, key, value);
                }
            };
            String value = storage.get(key);
            String v = substVars(value, key, cycles, this, wrapper, false, finalSubstitution, finalSubstitution);
            return v;
        }
    }
}
