/*
 * Copyright 2017-present Open Networking Laboratory
 *
 * Licensed 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.onosproject.ui.impl.lion;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.io.CharStreams;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static java.nio.charset.StandardCharsets.UTF_8;

/**
 * A Java representation of a lion configuration file. You can create one with
 * something like the following:
 * <pre>
 *     String filepath = "/path/to/some/file.lioncfg";
 *     LionConfig cfg = new LionConfig().load(filepath);
 * </pre>
 */
public class LionConfig {
    private static final Pattern RE_COMMENT = Pattern.compile("^\\s*#.*");
    private static final Pattern RE_BLANK = Pattern.compile("^\\s*$");

    static final Pattern RE_IMPORT =
            Pattern.compile("^(\\S+)\\s+import\\s+(.*)$");

    private static final String BUNDLE = "bundle";
    private static final String ALIAS = "alias";
    private static final String FROM = "from";
    private static final String STAR = "*";
    private static final char SPC = ' ';
    private static final char DOT = '.';

    private List<String> lines;
    private List<String> badLines;

    private CmdBundle bundle;
    private final Set<CmdAlias> aliases = new TreeSet<>();
    private final Set<CmdFrom> froms = new TreeSet<>();

    private Map<String, String> aliasMap;
    private Map<String, Set<String>> fromMap;

    /**
     * Loads in the specified file and attempts to parse it as a
     * {@code .lioncfg} format file.
     *
     * @param source path to .lioncfg file
     * @return the instance
     * @throws IllegalArgumentException if there is a problem reading the file
     */
    public LionConfig load(String source) {
        try (Reader r = new InputStreamReader(getClass().getResourceAsStream(source),
                                              UTF_8)) {
            lines = CharStreams.readLines(r);
        } catch (IOException e) {
            throw new IllegalArgumentException("Failed to read: " + source, e);
        }

        stripCommentsAndWhitespace();
        parse();
        processAliases();
        processFroms();

        return this;
    }


    private boolean isCommentOrBlank(String s) {
        return RE_COMMENT.matcher(s).matches() || RE_BLANK.matcher(s).matches();
    }


    private void stripCommentsAndWhitespace() {
        if (lines != null) {
            lines.removeIf(this::isCommentOrBlank);
        }
    }

    private void parse() {
        badLines = new ArrayList<>();

        lines.forEach(l -> {
            int i = l.indexOf(SPC);
            if (i < 1) {
                badLines.add(l);
                return;
            }
            String keyword = l.substring(0, i);
            String params = l.substring(i + 1);

            switch (keyword) {
                case BUNDLE:
                    CmdBundle cb = new CmdBundle(l, params);

                    if (bundle != null) {
                        // we can only declare the bundle once
                        badLines.add(l);
                    } else {
                        bundle = cb;
                    }
                    break;

                case ALIAS:
                    CmdAlias ca = new CmdAlias(l, params);
                    if (ca.malformed) {
                        badLines.add(l);
                    } else {
                        aliases.add(ca);
                    }
                    break;

                case FROM:
                    CmdFrom cf = new CmdFrom(l, params);
                    if (cf.malformed) {
                        badLines.add(l);
                    } else {
                        froms.add(cf);
                    }
                    break;

                default:
                    badLines.add(l);
                    break;
            }
        });
    }

    private void processAliases() {
        aliasMap = new HashMap<>(aliasCount());
        aliases.forEach(a -> aliasMap.put(a.alias, a.subst));
    }

    private void processFroms() {
        fromMap = new HashMap<>(fromCount());
        froms.forEach(f -> {
            f.expandAliasIfAny(aliasMap);
            if (singleStarCheck(f)) {
                fromMap.put(f.expandedRes, f.keys);
            } else {
                badLines.add(f.orig);
            }
        });
    }

    private boolean singleStarCheck(CmdFrom from) {
        from.starred = false;
        Set<String> keys = from.keys();
        for (String k : keys) {
            if (STAR.equals(k)) {
                from.starred = true;
            }
        }
        return !from.starred || keys.size() == 1;
    }

    @Override
    public String toString() {
        int nlines = lines == null ? 0 : lines.size();
        return String.format("LionConfig{#lines=%d}", nlines);
    }

    /**
     * Returns the configured bundle ID for this config.
     *
     * @return the bundle ID
     */
    String id() {
        return bundle == null ? null : bundle.id;
    }

    /**
     * Returns the number of aliases configured in this config.
     *
     * @return the alias count
     */
    int aliasCount() {
        return aliases.size();
    }

    /**
     * Returns the number of from...import lines configured in this config.
     *
     * @return the number of from...import lines
     */
    int fromCount() {
        return froms.size();
    }

    /**
     * Returns the substitution string for the given alias.
     *
     * @param a the alias
     * @return the substitution
     */
    String alias(String a) {
        return aliasMap.get(a);
    }

    /**
     * Returns the number of keys imported from the specified resource.
     *
     * @param res the resource
     * @return number of keys imported from that resource
     */
    int fromKeyCount(String res) {
        Set<String> keys = fromMap.get(res);
        return keys == null ? 0 : keys.size();
    }

    /**
     * Returns true if the specified resource exists and contains the
     * given key.
     *
     * @param res the resource
     * @param key the key
     * @return true, if resource exists and contains the key; false otherwise
     */
    boolean fromContains(String res, String key) {
        Set<String> keys = fromMap.get(res);
        return keys != null && keys.contains(key);
    }

    /**
     * Returns the set of (expanded) "from" entries in this configuration.
     *
     * @return the entries
     */
    public Set<CmdFrom> entries() {
        return froms;
    }

    /**
     * Returns the number of parse errors detected.
     *
     * @return number of bad lines
     */
    public int errorCount() {
        return badLines.size();
    }

    /**
     * Returns the lines that failed the parser.
     *
     * @return the erroneous lines in the config
     */
    public List<String> errorLines() {
        return ImmutableList.copyOf(badLines);
    }

    // ==== Mini class hierarchy of command types

    private abstract static class Cmd {
        final String orig;
        boolean malformed = false;

        Cmd(String orig) {
            this.orig = orig;
        }

        /**
         * Returns the original string from the configuration file.
         *
         * @return original from string
         */
        public String orig() {
            return orig;
        }
    }

    private static final class CmdBundle extends Cmd {
        private final String id;

        private CmdBundle(String orig, String params) {
            super(orig);
            id = params;
        }

        @Override
        public String toString() {
            return "CmdBundle{id=\"" + id + "\"}";
        }
    }

    private static final class CmdAlias extends Cmd
            implements Comparable<CmdAlias> {
        private final String alias;
        private final String subst;

        private CmdAlias(String orig, String params) {
            super(orig);
            int i = params.indexOf(SPC);
            if (i < 1) {
                malformed = true;
                alias = null;
                subst = null;
            } else {
                alias = params.substring(0, i);
                subst = params.substring(i + 1);
            }
        }

        @Override
        public String toString() {
            return "CmdAlias{alias=\"" + alias + "\", subst=\"" + subst + "\"}";
        }

        @Override
        public int compareTo(CmdAlias o) {
            return alias.compareTo(o.alias);
        }
    }

    /**
     * Represents a "from {res} import {stuff}" command in the configuration.
     */
    public static final class CmdFrom extends Cmd
            implements Comparable<CmdFrom> {
        private final String rawRes;
        private final Set<String> keys;
        private String expandedRes;
        private boolean starred = false;

        private CmdFrom(String orig, String params) {
            super(orig);
            Matcher m = RE_IMPORT.matcher(params);
            if (!m.matches()) {
                malformed = true;
                rawRes = null;
                keys = null;
            } else {
                rawRes = m.group(1);
                keys = genKeys(m.group(2));
            }
        }

        private Set<String> genKeys(String keys) {
            String[] k = keys.split("\\s*,\\s*");
            Set<String> allKeys = new HashSet<>();
            Collections.addAll(allKeys, k);
            return ImmutableSortedSet.copyOf(allKeys);
        }

        private void expandAliasIfAny(Map<String, String> aliases) {
            String expanded = rawRes;
            int i = rawRes.indexOf(DOT);
            if (i > 0) {
                String alias = rawRes.substring(0, i);
                String sub = aliases.get(alias);
                if (sub != null) {
                    expanded = sub + rawRes.substring(i);
                }
            }
            expandedRes = expanded;
        }

        @Override
        public String toString() {
            return "CmdFrom{res=\"" + rawRes + "\", keys=" + keys + "}";
        }

        @Override
        public int compareTo(CmdFrom o) {
            return rawRes.compareTo(o.rawRes);
        }

        /**
         * Returns the resource bundle name from which to import things.
         *
         * @return the resource bundle name
         */
        public String res() {
            return expandedRes;
        }

        /**
         * Returns the set of keys which should be imported.
         *
         * @return the keys to import
         */
        public Set<String> keys() {
            return keys;
        }

        /**
         * Returns true if this "from" command is importing ALL keys from
         * the specified resource; false otherwise.
         *
         * @return true, if importing ALL keys; false otherwise
         */
        public boolean starred() {
            return starred;
        }
    }
}
