/*
 * 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.Resources;

import java.io.IOException;
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 com.google.common.io.Resources.getResource;
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 {
            lines = Resources.readLines(getResource(getClass(), source), UTF_8);
        } 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;
        }
    }

    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;
        }
    }
}
