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

import static com.google.common.base.Preconditions.checkArgument;
import java.util.Optional;

import org.onosproject.net.DeviceId;
import org.onosproject.yang.model.KeyLeaf;
import org.onosproject.yang.model.ListKey;
import org.onosproject.yang.model.NodeKey;
import org.onosproject.yang.model.ResourceId;
import org.onosproject.yang.model.SchemaId;

import com.google.common.annotations.Beta;

/**
 * Utility related to device ResourceId.
 */
@Beta
public abstract class DeviceResourceIds {

    // assuming following device tree structure
    // - "/"
    //    +- devices
    //         +- device (=device root node:ListKey)


    /**
     * SchemaId namespace for DCS defined nodes.
     */
    public static final String DCS_NAMESPACE = "org.onosproject.dcs";

    // FIXME '/' is problematic name from RFC 7950/7951 point of view
    /**
     * SchemaId name for root node.
     */
    public static final String ROOT_NAME = "/";
    /**
     * SchemaId name for devices node.
     */
    public static final String DEVICES_NAME = "devices";
    public static final SchemaId DEVICES_SCHEMA = new SchemaId(DEVICES_NAME, DCS_NAMESPACE);
    /**
     * SchemaId name for device node.
     */
    public static final String DEVICE_NAME = "device";
    public static final SchemaId DEVICE_SCHEMA = new SchemaId(DEVICE_NAME, DCS_NAMESPACE);
    /**
     * KeyLeaf {@code name}, which holds DeviceId information on device node.
     */
    public static final String DEVICE_ID_KL_NAME = "device-id";

    /**
     * Absolute ResourceId pointing at root node.
     * @deprecated Use {@link ResourceIds#ROOT_ID} instead
     */
    @Deprecated
    public static final ResourceId ROOT_ID = ResourceIds.ROOT_ID;

    /**
     * Absolute ResourceId pointing at 'devices' node.
     */
    public static final ResourceId DEVICES_ID = ResourceId.builder()
            .addBranchPointSchema(ROOT_NAME, DCS_NAMESPACE)
            .addBranchPointSchema(DEVICES_NAME, DCS_NAMESPACE)
            .build();


    static final NodeKey<?> ROOT_NODE =
            NodeKey.builder().schemaId(ROOT_NAME, DCS_NAMESPACE).build();

    /**
     * nodeKeys index for root node.
     */
    @Deprecated
    static final int ROOT_INDEX = 0;
    /**
     * nodeKeys index relative from root for devices node.
     */
    static final int DEVICES_INDEX = 1;
    /**
     * nodeKeys index relative from root for device node.
     */
    static final int DEVICE_INDEX = 2;

    /**
     * Converts root relative ResourceId used by DynamicConfigEvent.
     *
     * @param rootRelative resource Id
     * @return absolute ResourceId.
     */
    @Beta
    public static ResourceId toAbsolute(ResourceId rootRelative) {
        if (ResourceIds.startsWithRootNode(rootRelative)) {
            return rootRelative;
        }
        return ResourceIds.concat(ResourceIds.ROOT_ID, rootRelative);
    }

    /**
     * Tests if specified path points to root node of a Device.
     *
     * @param path to test.
     * @return true if path points to root node of a Device.
     */
    public static boolean isDeviceRootNode(ResourceId path) {
        if (ResourceIds.startsWithRootNode(path)) {
            return path.nodeKeys().size() == 3 &&
                    isUnderDeviceRootNode(path);
        } else {
            return path.nodeKeys().size() == 2 &&
                    isUnderDeviceRootNode(path);
        }
    }

    /**
     * Tests if specified path points to root node of a Device or it's subtree.
     *
     * @param path to test.
     * @return true if path points to root node of a Device.
     */
    public static boolean isUnderDeviceRootNode(ResourceId path) {
        int rootIdx = ResourceIds.startsWithRootNode(path) ? 0 : -1;
        return path.nodeKeys().size() >= rootIdx + 3 &&
                DEVICE_SCHEMA.equals(path.nodeKeys().get(rootIdx + DEVICE_INDEX).schemaId()) &&
                (path.nodeKeys().get(rootIdx + DEVICE_INDEX) instanceof ListKey) &&
                DEVICES_SCHEMA.equals(path.nodeKeys().get(rootIdx + DEVICES_INDEX).schemaId());    }

    /**
     * Tests if specified path points to root or devices node.
     *
     * @param path to test.
     * @return true if path points to root node of a Device.
     */
    public static boolean isRootOrDevicesNode(ResourceId path) {
        return isDevicesNode(path) ||
               isRootNode(path);
    }

    public static boolean isDevicesNode(ResourceId path) {
        int rootIdx = ResourceIds.startsWithRootNode(path) ? 0 : -1;
        return path.nodeKeys().size() == rootIdx + 2 &&
                DEVICES_SCHEMA.equals(path.nodeKeys().get(rootIdx + DEVICES_INDEX).schemaId());
    }

    public static boolean isRootNode(ResourceId path) {
        return path.nodeKeys().size() == 1 &&
                ROOT_NODE.equals(path.nodeKeys().get(ROOT_INDEX));
    }

    /**
     * Transforms device resource path to DeviceId.
     *
     * @param path pointing to somewhere in the subtree of a device
     * @return DeviceId
     * @throws IllegalArgumentException if the path was not part of devices tree
     */
    public static DeviceId toDeviceId(ResourceId path) {
        checkArgument(isUnderDeviceRootNode(path), path);
        // FIXME if we decide to drop any of intermediate nodes
        //        "/" - "devices" - "device"
        int rootIdx = ResourceIds.startsWithRootNode(path) ? 0 : -1;
        return toDeviceId(path.nodeKeys().get(rootIdx + DEVICE_INDEX));
    }

    /**
     * Transforms root node of a device to corresponding DeviceId.
     *
     * @param deviceRoot NodeKey of a device root node
     * @return DeviceId
     * @throws IllegalArgumentException if not a device node
     */
    public static DeviceId toDeviceId(NodeKey<?> deviceRoot) {
        if (!DEVICE_SCHEMA.equals(deviceRoot.schemaId())) {
            throw new IllegalArgumentException(deviceRoot + " is not a device node");
        }

        if (deviceRoot instanceof ListKey) {
            ListKey device = (ListKey) deviceRoot;
            Optional<DeviceId> did = device.keyLeafs().stream()
                // TODO If we decide to define ONOS schema for device ID,
                // use whole schemaId to filter, not only by name
                .filter(kl -> DEVICE_ID_KL_NAME.equals(kl.leafSchema().name()))
                .map(KeyLeaf::leafValAsString)
                .map(DeviceId::deviceId)
                .findFirst();

            if (did.isPresent()) {
                return did.get();
            }
            throw new IllegalArgumentException("device-id not found in " + deviceRoot);
        }
        throw new IllegalArgumentException("Unexpected type " + deviceRoot.getClass());
    }

    /**
     * Transforms DeviceId into a ResourceId pointing to device root node.
     *
     * @param deviceId to transform
     * @return absolute ResourceId
     */
    public static ResourceId toResourceId(DeviceId deviceId) {
        return ResourceId.builder()
                .addBranchPointSchema(ROOT_NAME, DCS_NAMESPACE)
                .addBranchPointSchema(DEVICES_NAME, DCS_NAMESPACE)
                .addBranchPointSchema(DEVICE_NAME, DCS_NAMESPACE)
                .addKeyLeaf(DEVICE_ID_KL_NAME, DCS_NAMESPACE, deviceId.toString())
                .build();
    }

}
