/*
 * 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.sling.distribution.component.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.sling.commons.osgi.PropertiesUtil;

//TODO: Consider removing it

/**
 * Utility class that provides parsing from linear set of properties into a tree of properties
 */
public class SettingsUtils {

    public static final String COMPONENT_NAME_DEFAULT = "(name=default)";
    private static final String COMPONENT_ROOT = "";
    private static final char COMPONENT_DELIM = '/';
    private static final char COMPONENT_MAP_BEGIN = '[';
    private static final char COMPONENT_MAP_END = ']';
    private static final char COMPONENT_MAP_DELIM = '=';


    /**
     * packageExporter/propertyKey=propertyValue
     * packageExporter/endpoint[flag]=propertyValue
     *
     * packageExporter/packageBuilder/propertyKey=propertyValue
     *
     * propertyKey=propertyValue
     * trigger[0]/propertyKey=propertyValue
     * trigger[0]/propertyKey=propertyValue
     *
     * @param lines the property lines
     * @return a {@link Map} of the property names -> property values
     */
    public static Map<String, Object> parseLines(String[] lines) {
        Map<String, Object> result = new HashMap<String, Object>();

        Map<String, List<String>> linesMap = toLinesMap(lines);

        for (Map.Entry<String, List<String>> entry : linesMap.entrySet()) {
            String componentName = entry.getKey();
            List<String> var = entry.getValue();
            String[] componentLines = var.toArray(new String[var.size()]);

            if (COMPONENT_ROOT.equals(componentName)) {
                Map<String, String> map = PropertiesUtil.toMap(componentLines, new String[0]);
                result.putAll(map);
            } else {
                Map<String, Object> componentMap = parseLines(componentLines);
                result.put(componentName, componentMap);
            }
        }

        result = collapseMap(result);
        return result;
    }

    private static Map<String, List<String>> toLinesMap(String[] lines) {
        Map<String, List<String>> result = new HashMap<String, List<String>>();


        for (String line : lines) {
            int firstMapDelim = line.indexOf(COMPONENT_MAP_DELIM);
            if (firstMapDelim < 0) {
                continue;
            }

            int firstDelim = line.substring(0, firstMapDelim).indexOf(COMPONENT_DELIM);
            String key = COMPONENT_ROOT;
            String value = line;

            if (firstDelim >= 0) {
                key = line.substring(0, firstDelim);
                value = line.substring(firstDelim + 1);
            }


            if (!result.containsKey(key)) {
                result.put(key, new ArrayList<String>());
            }

            List<String> exitingLines = result.get(key);
            exitingLines.add(value);

        }

        return result;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private static Map<String, Object> collapseMap(Map<String, Object> valueMap) {

        Map<String, Object> result = new HashMap<String, Object>();

        for (Map.Entry<String, Object> entry : valueMap.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            int beginDelim = key.indexOf(COMPONENT_MAP_BEGIN);
            int endDelim = key.indexOf(COMPONENT_MAP_END);

            if (beginDelim >= 0 && endDelim > beginDelim) {
                String newKey = key.substring(0, beginDelim);
                String partialKey = key.substring(beginDelim + 1, endDelim);


                boolean isNumber = isNumber(partialKey);

                if (!result.containsKey(newKey)) {
                    result.put(newKey, isNumber ? new ArrayList<Object>() : new HashMap<String, Object>());
                }

                Object existingObject = result.get(newKey);
                if (existingObject instanceof Map) {
                    ((Map) existingObject).put(partialKey, value);
                } else if (existingObject instanceof List) {
                    ((List) existingObject).add(value);
                } else {
                    // skip if there is already something else in there
                }
            } else {
                result.put(key, value);
            }
        }

        return result;

    }

    private static boolean isNumber(String value) {
        try {
            Integer.parseInt(value);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }


    private static <AType> Map<String, AType> toMap(List<AType> aList, String prefix) {
        Map<String, AType> result = new TreeMap<String, AType>();
        for (int i = 0; i < aList.size(); i++) {
            result.put(prefix + i, aList.get(i));
        }

        return result;
    }


    public static Map<String, String> toUriMap(Object obj) {
        Map<String, String> uriMap = PropertiesUtil.toMap(obj, new String[0]);

        if (uriMap.size() == 0) {
            String[] endpoints = PropertiesUtil.toStringArray(obj, new String[0]);
            endpoints = removeEmptyEntries(endpoints);
            uriMap = toMap(Arrays.asList(endpoints), "endpoint");
        }
        return uriMap;
    }

    public static String[] removeEmptyEntries(String[] array) {
        if (array == null || array.length == 0) {
            return array;
        }

        List<String> result = new ArrayList<String>();
        for (String entry : array) {
            entry = removeEmptyEntry(entry);

            if (entry != null) {
                result.add(entry);
            }
        }

        if (result.size() == 0) {
            return null;
        }

        return result.toArray(new String[result.size()]);
    }

    public static String[] removeEmptyEntries(String[] array, String[] defaultArray) {
        String[] result = removeEmptyEntries(array);
        if (result == null) {
            return defaultArray;
        } else {
            return result;
        }
    }



    public static String removeEmptyEntry(String entry) {
        if (entry == null) {
            return null;
        }

        entry = entry.trim();


        if (entry.length() == 0) {
            return null;
        }

        return entry;
    }

    public static Map<String, String> removeEmptyEntries(Map<String, String> map) {
        if (map == null) {
            return null;
        }

        Map<String, String> result = new HashMap<String, String>();
        for(Map.Entry<String, String> entry : map.entrySet()) {
            String key = removeEmptyEntry(entry.getKey());
            String value = removeEmptyEntry(entry.getValue());

            if (key != null && value!= null) {
                result.put(key, value);
            }
        }

        if (result.size() == 0) {
            return null;
        }

       return result;
    }


    public static Map<String, String> expandUriMap(Map<String, String> map, Map<String, String> aliases) {
        Map<String, String> result = new TreeMap<String, String>(map);

        for (Map.Entry<String, String> aliasEntry : aliases.entrySet()) {
            if (aliasEntry.getValue() != null && map.containsKey(aliasEntry.getValue())) {
                result.put(aliasEntry.getKey(), map.get(aliasEntry.getValue()));
            }

        }

        return result;
    }
}
