/*
 * 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.maven.surefire.booter;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.maven.surefire.shared.utils.StringUtils;

/**
 * @author Kristian Rosenvold
 */
public class PropertiesWrapper implements KeyValueSource {
    private final Map<String, String> properties;

    public PropertiesWrapper(Map<String, String> properties) {
        if (properties == null) {
            throw new IllegalStateException("Properties cannot be null");
        }
        this.properties = properties;
    }

    public Map<String, String> getProperties() {
        return properties;
    }

    public void setAsSystemProperties() {
        for (Map.Entry<String, String> entry : properties.entrySet()) {
            System.setProperty(entry.getKey(), entry.getValue());
        }
    }

    public String getProperty(String key) {
        return properties.get(key);
    }

    public boolean getBooleanProperty(String propertyName) {
        return Boolean.parseBoolean(properties.get(propertyName));
    }

    public int getIntProperty(String propertyName) {
        return Integer.parseInt(properties.get(propertyName));
    }

    public Long getLongProperty(String propertyName) {
        String number = getProperty(propertyName);
        return number == null ? null : Long.parseLong(number);
    }

    public File getFileProperty(String key) {
        final String property = getProperty(key);
        if (property == null) {
            return null;
        }
        TypeEncodedValue typeEncodedValue = new TypeEncodedValue(File.class.getName(), property);
        return (File) typeEncodedValue.getDecodedValue();
    }

    public List<String> getStringList(String propertyPrefix) {
        List<String> result = new ArrayList<>();
        for (int i = 0; ; i++) {
            String value = getProperty(propertyPrefix + i);

            if (value == null) {
                return result;
            }

            result.add(value);
        }
    }

    /**
     * Retrieves as single object that is persisted with type encoding
     *
     * @param key The key for the propery
     * @return The object, of a supported type
     */
    public TypeEncodedValue getTypeEncodedValue(String key) {
        String typeEncoded = getProperty(key);
        if (typeEncoded != null) {
            int typeSep = typeEncoded.indexOf("|");
            String type = typeEncoded.substring(0, typeSep);
            String value = typeEncoded.substring(typeSep + 1);
            return new TypeEncodedValue(type, value);
        } else {
            return null;
        }
    }

    Classpath getClasspath(String prefix) {
        List<String> elements = getStringList(prefix);
        return new Classpath(elements);
    }

    public void setClasspath(String prefix, Classpath classpath) {
        List classpathElements = classpath.getClassPath();
        for (int i = 0, size = classpathElements.size(); i < size; ++i) {
            String element = (String) classpathElements.get(i);
            setProperty(prefix + i, element);
        }
    }

    public void setProperty(String key, String value) {
        if (value != null) {
            properties.put(key, value);
        }
    }

    public void addList(List items, String propertyPrefix) {
        if (items != null && !items.isEmpty()) {
            int i = 0;
            for (Object item : items) {
                if (item == null) {
                    throw new NullPointerException(propertyPrefix + i + " has null value");
                }

                String[] stringArray = StringUtils.split(item.toString(), ",");

                for (String aStringArray : stringArray) {
                    properties.put(propertyPrefix + i, aStringArray);
                    i++;
                }
            }
        }
    }

    @Override
    public void copyTo(Map<Object, Object> target) {
        target.putAll(properties);
    }
}
