/*
 * 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";

    /**
     * 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();
    }

}
