/*
 * Copyright 2016-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.yms.app.ych.defaultcodecs.utils;

import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import org.onosproject.yms.app.ych.YchException;
import org.onosproject.yms.ydt.YdtBuilder;
import org.onosproject.yms.ydt.YdtContextOperationType;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.yms.ydt.YdtContextOperationType.NONE;
import static org.onosproject.yms.ydt.YdtType.SINGLE_INSTANCE_NODE;

/**
 * Utils to complete the conversion between JSON and YDT(YANG DATA MODEL).
 */
public final class DefaultCodecUtils {

    private static final Splitter SLASH_SPLITTER = Splitter.on('/');
    private static final Splitter COMMA_SPLITTER = Splitter.on(',');
    private static final String EQUAL = "=";
    private static final String COMMA = ",";
    private static final String COLON = ":";
    private static final String URI_ENCODING_CHAR_SET = "ISO-8859-1";
    private static final String URI_NULL_CHECK_ERROR = "uri identifier " +
            "should not be null";
    private static final String URI_MODULE_FORMAT = "Illegal URI, First " +
            "node should be in format \"moduleName:nodeName\"";

    private static final String URI_LEAF_FORMAT = "Illegal URI, List or " +
            "Leaf-list node should be in format \"nodeName=key\"or " +
            "\"nodeName=instance-value\"";

    // no instantiation
    private DefaultCodecUtils() {
    }

    /**
     * Converts  URI identifier to YDT builder.
     *
     * @param identifier the uri identifier from web request
     * @param builder    the base YDT builder
     * @param ydtOpType  the YDT context operation type
     * @return the YDT builder with the tree info of identifier
     */
    public static YdtBuilder convertUriToYdt(
            String identifier,
            YdtBuilder builder,
            YdtContextOperationType ydtOpType) {
        checkNotNull(identifier, URI_NULL_CHECK_ERROR);
        List<String> segmentPaths =
                urlPathArgsDecode(SLASH_SPLITTER.split(identifier));
        if (segmentPaths.isEmpty()) {
            return null;
        }
        processPathSegments(segmentPaths, builder, ydtOpType);
        return builder;
    }

    /**
     * Returns true, if the list is not null and non-empty; false otherwise.
     *
     * @param object list object
     * @return true, if the list is not null and non-empty; false otherwise
     */
    public static boolean isNonEmpty(List object) {
        return object != null && !object.isEmpty();
    }

    /**
     * Converts a list of path segments to a YDT builder tree.
     *
     * @param paths     the list of path segments split from URI
     * @param builder   the base YDT builder
     * @param ydtOpType the YDT context operation type
     * @return the YDT builder with the tree info of paths
     */
    private static YdtBuilder processPathSegments(
            List<String> paths,
            YdtBuilder builder,
            YdtContextOperationType ydtOpType) {
        if (paths.isEmpty()) {
            return builder;
        }
        boolean isLastNode = paths.size() == 1;
        YdtContextOperationType thisOpType = isLastNode ? ydtOpType : NONE;

        final String path = paths.iterator().next();
        if (path.contains(COLON)) {
            addModule(builder, path);
            addNode(path, builder, thisOpType);
        } else if (path.contains(EQUAL)) {
            addListOrLeafList(path, builder, thisOpType);
        } else {
            addLeaf(path, builder, thisOpType);
        }

        if (isLastNode) {
            return builder;
        }
        List<String> remainPaths = paths.subList(1, paths.size());
        processPathSegments(remainPaths, builder, ydtOpType);

        return builder;
    }

    /**
     * Returns YDT builder after adding module node.
     *
     * @param builder YDT builder
     * @param path    path segment
     * @return the YDT builder
     */
    private static YdtBuilder addModule(YdtBuilder builder, String path) {
        String moduleName = getPreSegment(path, COLON);
        if (moduleName == null) {
            throw new YchException(URI_MODULE_FORMAT);
        }
        builder.addChild(moduleName, null, SINGLE_INSTANCE_NODE);
        return builder;
    }

    /**
     * Returns YDT builder after adding single instance node.
     *
     * @param path      path segments
     * @param builder   YDT builder
     * @param ydtOpType YDT context operation type
     * @return the YDT builder
     */
    private static YdtBuilder addNode(String path, YdtBuilder builder,
                                      YdtContextOperationType ydtOpType) {
        String nodeName = getPostSegment(path, COLON);
        builder.addChild(nodeName, null, SINGLE_INSTANCE_NODE, ydtOpType);
        return builder;
    }

    /**
     * Returns YDT builder after adding multi instance node.
     *
     * @param path    path segments
     * @param builder YDT builder
     * @param opType  the YDT context operation type
     * @return the YDT builder
     */
    private static YdtBuilder addListOrLeafList(
            String path,
            YdtBuilder builder,
            YdtContextOperationType opType) {
        String nodeName = getPreSegment(path, EQUAL);
        String keyStr = getPostSegment(path, EQUAL);
        if (keyStr == null) {
            throw new YchException(URI_LEAF_FORMAT);
        }
        builder.setDefaultEditOperationType(opType);
        if (keyStr.contains(COMMA)) {
            List<String> keys = Lists.newArrayList(
                    COMMA_SPLITTER.split(keyStr));
            builder.addMultiInstanceChild(nodeName, null, keys, null);
        } else {
            builder.addMultiInstanceChild(nodeName, null,
                                          Lists.newArrayList(keyStr), null);
        }
        return builder;
    }

    /**
     * Returns YDT builder after adding leaf.
     *
     * @param path      path segments
     * @param builder   YDT builder
     * @param ydtOpType YDT context operation type
     * @return the YDT builder
     */
    private static YdtBuilder addLeaf(String path, YdtBuilder builder,
                                      YdtContextOperationType ydtOpType) {
        checkNotNull(path);
        builder.addChild(path, null, ydtOpType);
        return builder;
    }

    /**
     * Returns the node name before the specified character in the string.
     *
     * @param path      path segment
     * @param splitChar character in the string
     * @return the node name string
     */
    private static String getPreSegment(String path, String splitChar) {
        int idx = path.indexOf(splitChar);
        if (idx == -1) {
            return null;
        }

        if (path.indexOf(':', idx + 1) != -1) {
            return null;
        }

        return path.substring(0, idx);
    }

    /**
     * Returns the string after the specified character in the string.
     *
     * @param path      path segment
     * @param splitChar character in the string
     * @return the substring after specified character
     */
    private static String getPostSegment(String path, String splitChar) {
        int idx = path.indexOf(splitChar);
        if (idx == -1) {
            return path;
        }

        if (path.indexOf(splitChar, idx + 1) != -1) {
            return null;
        }

        return path.substring(idx + 1);
    }

    /**
     * Converts a list of path from the original format to ISO-8859-1 code.
     *
     * @param paths the original paths
     * @return list of decoded paths
     */
    private static List<String> urlPathArgsDecode(Iterable<String> paths) {
        try {
            List<String> decodedPathArgs = new ArrayList<>();
            for (String pathArg : paths) {
                String decode = URLDecoder.decode(pathArg,
                                                  URI_ENCODING_CHAR_SET);
                decodedPathArgs.add(decode);
            }
            return decodedPathArgs;
        } catch (UnsupportedEncodingException e) {
            throw new YchException("Invalid URL path arg '" + paths + "': ", e);
        }
    }
}
