/*
 * Copyright 2014 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.net;

import com.google.common.base.MoreObjects;

import java.util.Objects;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

/**
 * Abstraction of a network connection point expressed as a pair of the
 * network element identifier and port number.
 */
public class ConnectPoint {

    private final ElementId elementId;
    private final PortNumber portNumber;

    /**
     * Creates a new connection point.
     *
     * @param elementId  network element identifier
     * @param portNumber port number
     */
    public ConnectPoint(ElementId elementId, PortNumber portNumber) {
        this.elementId = elementId;
        this.portNumber = portNumber;
    }

    /**
     * Returns the network element identifier.
     *
     * @return element identifier
     */
    public ElementId elementId() {
        return elementId;
    }

    /**
     * Returns the identifier of the infrastructure device if the connection
     * point belongs to a network element which is indeed an infrastructure
     * device.
     *
     * @return network element identifier as a device identifier
     * @throws java.lang.IllegalStateException if connection point is not
     *                                         associated with a device
     */
    public DeviceId deviceId() {
        if (elementId instanceof DeviceId) {
            return (DeviceId) elementId;
        }
        throw new IllegalStateException("Connection point not associated " +
                                                "with an infrastructure device");
    }

    /**
     * Returns the identifier of the infrastructure device if the connection
     * point belongs to a network element which is indeed an end-station host.
     *
     * @return network element identifier as a host identifier
     * @throws java.lang.IllegalStateException if connection point is not
     *                                         associated with a host
     */
    public HostId hostId() {
        if (elementId instanceof HostId) {
            return (HostId) elementId;
        }
        throw new IllegalStateException("Connection point not associated " +
                                                "with an end-station host");
    }

    /**
     * Returns the identifier of the infrastructure device if the connection
     * point belongs to a network element which is indeed an ip of pcc
     * client identifier.
     *
     * @return network element identifier as a pcc client identifier
     * @throws java.lang.IllegalStateException if connection point is not
     *                                         associated with a pcc client
     */
    public IpElementId ipElementId() {
        if (elementId instanceof IpElementId) {
            return (IpElementId) elementId;
        }
        throw new IllegalStateException("Connection point not associated " +
                                                "with an pcc client");
    }

    /**
     * Returns the connection port number.
     *
     * @return port number
     */
    public PortNumber port() {
        return portNumber;
    }

    /**
     * Parse a device connect point from a string.
     * The connect point should be in the format "deviceUri/portNumber".
     *
     * @param string string to parse
     * @return a ConnectPoint based on the information in the string.
     */
    public static ConnectPoint deviceConnectPoint(String string) {
        checkNotNull(string);
        String[] splitted = string.split("/");
        checkArgument(splitted.length == 2,
                      "Connect point must be in \"deviceUri/portNumber\" format");

        return new ConnectPoint(DeviceId.deviceId(splitted[0]),
                                PortNumber.portNumber(splitted[1]));
    }

    /**
     * Parse a host connect point from a string.
     * The connect point should be in the format "hostId/vlanId/portNumber".
     *
     * @param string string to parse
     * @return a ConnectPoint based on the information in the string.
     */
    public static ConnectPoint hostConnectPoint(String string) {
        checkNotNull(string);
        String[] splitted = string.split("/");
        checkArgument(splitted.length == 3,
                      "Connect point must be in \"hostId/vlanId/portNumber\" format");

        int lastSlash = string.lastIndexOf("/");

        return new ConnectPoint(HostId.hostId(string.substring(0, lastSlash)),
                                PortNumber.portNumber(string.substring(lastSlash + 1, string.length())));
    }

    @Override
    public int hashCode() {
        return Objects.hash(elementId, portNumber);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj instanceof ConnectPoint) {
            final ConnectPoint other = (ConnectPoint) obj;
            return Objects.equals(this.elementId, other.elementId) &&
                    Objects.equals(this.portNumber, other.portNumber);
        }
        return false;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this)
                .add("elementId", elementId)
                .add("portNumber", portNumber)
                .toString();
    }

}
