/*
 * Copyright 2017-present Open Networking Foundation
 *
 * 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.config;

import java.util.Arrays;
import java.util.Iterator;

import java.util.LinkedList;
import java.util.List;

import org.onosproject.yang.model.KeyLeaf;
import org.onosproject.yang.model.LeafListKey;
import org.onosproject.yang.model.ListKey;
import org.onosproject.yang.model.NodeKey;
import org.onosproject.yang.model.ResourceId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.annotations.Beta;

// FIXME add non-trivial examples
/**
 * Utilities to work on the ResourceId.
 * <p>
 * Examples:
 * <dl>
 *  <dt>root node</dt>
 *   <dd>root</dd>
 * </dl>
 *
 */
//FIXME add javadocs
@Beta
public final class ResourceIdParser {

    private static final Logger log = LoggerFactory.getLogger(ResourceIdParser.class);

    /**
     * root node name.
     */
    public static final String ROOT = "root";

    /**
     * Separator between SchemaId components and value part.
     */
    public static final String NM_SEP = "#";
    // TODO not used in #parseResId(ResourceId)??
    public static final String VAL_SEP = "@";
    /**
     * Separator between ListKey schemaId and keyLeafs.
     */
    public static final String KEY_SEP = "$";
    /**
     * Separator between {@code NodeKey}s (~=tree nodes).
     */
    public static final String EL_SEP = "|";

    public static final String VAL_CHK = "\\@";
    public static final String KEY_CHK = "\\$";
    public static final String NM_CHK = "\\#";
    public static final String EL_CHK = "\\|";


    private ResourceIdParser() {

    }

    public static NodeKey getInstanceKey(ResourceId path) {
        int last = path.nodeKeys().size();
        NodeKey ret = path.nodeKeys().get(last - 1);
        if (ret instanceof NodeKey) {
            return ret;
        } else {
            return null;
        }
    }

    public static NodeKey getMultiInstanceKey(ResourceId path) {
        int last = path.nodeKeys().size();
        NodeKey ret = path.nodeKeys().get(last - 1);
        if (ret instanceof ListKey) {
            return ret;
        } else {
            return null;
        }
    }

    public static String getNamespace(String nmspc) {
        String ret = null;
        if (nmspc.contains(ResourceIdParser.KEY_SEP)) {
            ret = nmspc.split(KEY_CHK)[0];
        } else if (nmspc.contains(ResourceIdParser.VAL_SEP)) {
            ret = nmspc.split(VAL_CHK)[0];
        } else {
            ret = nmspc;
        }
        return ret;
    }

    public static String getKeyVal(String nmspc) {
        String ret = null;
        if (nmspc.contains(ResourceIdParser.VAL_SEP)) {
            ret = nmspc.split(VAL_CHK)[1];
        }
        return ret;
    }

    public static String appendMultiInstKey(String path, String leaf) {
        return (path + leaf.substring(leaf.indexOf(KEY_SEP)));
    }

    // 1.12.0 - not used by anyone
    @Deprecated
    public static String appendKeyLeaf(String path, String key) {
        return (path + EL_SEP + key);
    }

    // 1.12.0 - not used by anyone
    @Deprecated
    public static String appendKeyLeaf(String path, KeyLeaf key) {
        StringBuilder bldr = new StringBuilder();
        bldr.append(key.leafSchema().name());
        bldr.append(NM_SEP);
        bldr.append(key.leafSchema().namespace());
        bldr.append(NM_SEP);
        bldr.append(key.leafValue().toString());
        return (path + EL_SEP + bldr.toString());
    }

    public static String appendNodeKey(String path, NodeKey key) {
        // FIXME this is not handling root path exception
        return (path + EL_SEP + key.schemaId().name() + NM_SEP + key.schemaId().namespace());
    }

    public static String appendNodeKey(String path, String name, String nmSpc) {
        return (path + EL_SEP + name + NM_SEP + nmSpc);
    }

    public static String appendLeafList(String path, LeafListKey key) {
        return (path + VAL_SEP + key.asString());
    }

    public static String appendLeafList(String path, String val) {
        return (path + VAL_SEP + val);
    }

    public static String appendKeyList(String path, ListKey key) {
        StringBuilder bldr = new StringBuilder();
        for (KeyLeaf keyLeaf : key.keyLeafs()) {
            bldr.append(KEY_SEP);
            bldr.append(keyLeaf.leafSchema().name());
            bldr.append(NM_SEP);
            bldr.append(keyLeaf.leafSchema().namespace());
            bldr.append(NM_SEP);
            bldr.append(keyLeaf.leafValue().toString());
        }
        return (path + bldr.toString());
    }

    // 1.12.0 - not used by anyone
    @Deprecated
    public static String parseNodeKey(NodeKey key) {
        if (key == null) {
            return null;
        }
        StringBuilder bldr = new StringBuilder();
        if (key instanceof LeafListKey) {
            parseLeafList((LeafListKey) key, bldr);
        } else if (key instanceof ListKey) {
            parseKeyList((ListKey) key, bldr);
        } else {
            parseNodeKey(key, bldr);
        }
        return bldr.toString();
    }

    /**
     * Gets String representation of ResourceId.
     * <p>
     * <pre>
     *   ResourceId := 'root' ('|' element)*
     *   element := LeafListKey | ListKey | NodeKey
     *   SchemaId := [string SchemaId#name] '#' [string SchemaId#namespace]
     *   LeafListKey := SchemaId '#' [string representation of LeafListKey#value]
     *   ListKey := SchemaId (KeyLeaf)*
     *   KeyLeaf := '$' SchemaId '#' [string representation of KeyLeaf#leafValue]
     *   NodeKey := SchemaId
     * </pre>
     *
     * @param path to convert
     * @return String representation
     */
    public static String parseResId(ResourceId path) {
        StringBuilder bldr = new StringBuilder();
        bldr.append(ROOT);
        if (path == null) {
            return bldr.toString();
        }
        List<NodeKey> nodeKeyList = new LinkedList<>();
        Iterator<NodeKey> itr = path.nodeKeys().iterator();
        while (itr.hasNext()) {
            nodeKeyList.add(itr.next());
        }
        // exception for dealing with root
        if (nodeKeyList.get(0).schemaId().name().equals("/")) {
            nodeKeyList.remove(0);
        }
        for (NodeKey key : nodeKeyList) {
            bldr.append(EL_SEP);
            if (key instanceof LeafListKey) {
                parseLeafList((LeafListKey) key, bldr);
            } else if (key instanceof ListKey) {
                parseKeyList((ListKey) key, bldr);
            } else {
                parseNodeKey(key, bldr);
            }
        }
        return bldr.toString();
    }

    public static String[] getService(ResourceId path) {
        String[] res = new String[2];
        if (path == null) {
            return res;
        }
        int last = path.nodeKeys().size() - 1;
        res[0] = path.nodeKeys().get(last - 1).schemaId().name();
        res[1] = path.nodeKeys().get(last).schemaId().name();
        return res;
    }

    private static void parseLeafList(LeafListKey key, StringBuilder bldr) {
        bldr.append(key.schemaId().name());
        bldr.append(NM_SEP);
        bldr.append(key.schemaId().namespace());
        bldr.append(NM_SEP);
        bldr.append(key.asString());
    }

    private static void parseKeyList(ListKey key, StringBuilder bldr) {
        bldr.append(key.schemaId().name());
        bldr.append(NM_SEP);
        bldr.append(key.schemaId().namespace());
        Iterator<KeyLeaf> iter = key.keyLeafs().iterator();
        KeyLeaf next;
        while (iter.hasNext()) {
            next = iter.next();
            bldr.append(KEY_SEP);
            bldr.append(next.leafSchema().name());
            bldr.append(NM_SEP);
            bldr.append(next.leafSchema().namespace());
            bldr.append(NM_SEP);
            bldr.append(next.leafValue().toString());
        }
    }

    private static void parseNodeKey(NodeKey key, StringBuilder bldr) {
        bldr.append(key.schemaId().name());
        bldr.append(NM_SEP);
        bldr.append(key.schemaId().namespace());
    }

    public static ResourceId getResId(List<String> dpath) {
        ResourceId.Builder resBldr = new ResourceId.Builder();
        Iterator<String> itr = dpath.iterator();
        itr.next();
        while (itr.hasNext()) {
            String name = itr.next();
            if (name.contains(VAL_SEP)) {
                // dead branch? VAL_SEP never used in parseResId
                resBldr.addLeafListBranchPoint(name.substring(0, name.indexOf(NM_SEP)),
                        name.substring(name.indexOf(NM_SEP) + 1, name.indexOf(VAL_SEP)),
                        name.substring(name.indexOf(VAL_SEP) + 1));
            } else if (name.contains(KEY_SEP)) {
                String[] keys = name.split(KEY_CHK);
                String[] nm = keys[0].split(NM_CHK);
                resBldr.addBranchPointSchema(nm[0], nm[1]);
                for (int i = 1; i < keys.length; i++) {
                    String key = keys[i];
                    String[] el = keys[i].split(NM_CHK);
                    if (el.length != 3) {
                        throw new FailedException("Malformed event subject, cannot parse");
                    }
                    try {
                    resBldr.addKeyLeaf(el[0], el[1], el[2]);
                    } catch (Exception e) {
                        log.error("dpath={}", dpath);
                        log.error("name={}", name);
                        log.error("key={}", key);
                        log.error("el={}", Arrays.asList(el));
                        throw e;
                    }
                }
            } else {
                resBldr.addBranchPointSchema(name.substring(0, name.indexOf(NM_SEP)),
                        name.substring(name.indexOf(NM_SEP) + 1));
            }
        }
        return resBldr.build();
    }
}