/*
 * Copyright 2016 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.tetopology.management.api.node;

import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import org.onosproject.tetopology.management.api.EncodingType;
import org.onosproject.tetopology.management.api.SwitchingType;

import java.util.Arrays;
import java.util.BitSet;
import java.util.List;

/**
 * Default implementation of a tunnel termination point.
 */
public class DefaultTunnelTerminationPoint implements TunnelTerminationPoint {
    private final long ttpId;
    private final SwitchingType switchingLayer;
    private final EncodingType encodingLayer;
    private final BitSet flags;
    private final List<Long> interLayerLockList;
    private final List<LocalLinkConnectivity> localLinkConnectivityList;
    private final float[] availAdaptBandwidth;

    /**
     * Create a tunnel termination point.
     *
     * @param ttpId                     tunnel termination point id
     * @param switchingLayer            switching network layer to which this
     *                                  TTP belongs
     * @param encodingLayer             encoding layer to which this TTP belongs
     * @param flags                     the TTP flags
     * @param interLayerLockList        the supported inter-layer locks
     * @param localLinkConnectivityList the local link connectivity list
     * @param availAdaptBandwidth       the remaining adaptation bandwidth
     *                                  at each priority level
     */
    public DefaultTunnelTerminationPoint(long ttpId,
                                         SwitchingType switchingLayer,
                                         EncodingType encodingLayer,
                                         BitSet flags,
                                         List<Long> interLayerLockList,
                                         List<LocalLinkConnectivity> localLinkConnectivityList,
                                         float[] availAdaptBandwidth) {
        this.ttpId = ttpId;
        this.switchingLayer = switchingLayer;
        this.encodingLayer = encodingLayer;
        this.flags = flags;
        this.interLayerLockList = interLayerLockList != null ?
                Lists.newArrayList(interLayerLockList) : null;
        this.localLinkConnectivityList = localLinkConnectivityList != null ?
                Lists.newArrayList(localLinkConnectivityList) : null;
        this.availAdaptBandwidth = availAdaptBandwidth != null ?
                Arrays.copyOf(availAdaptBandwidth,
                              availAdaptBandwidth.length) : null;
    }

    @Override
    public long ttpId() {
        return ttpId;
    }

    @Override
    public SwitchingType switchingLayer() {
        return switchingLayer;
    }

    @Override
    public EncodingType encodingLayer() {
        return encodingLayer;
    }

    @Override
    public BitSet flags() {
        return flags;
    }

    @Override
    public List<Long> interLayerLockList() {
        if (interLayerLockList == null) {
            return null;
        }
        return ImmutableList.copyOf(interLayerLockList);
    }

    @Override
    public List<LocalLinkConnectivity> localLinkConnectivityList() {
        if (localLinkConnectivityList == null) {
            return null;
        }
        return ImmutableList.copyOf(localLinkConnectivityList);
    }

    @Override
    public float[] availAdaptBandwidth() {
        if (availAdaptBandwidth == null) {
            return null;
        }
        return Arrays.copyOf(availAdaptBandwidth, availAdaptBandwidth.length);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(ttpId, switchingLayer, encodingLayer, flags,
                                interLayerLockList, localLinkConnectivityList,
                                availAdaptBandwidth);
    }

    @Override
    public boolean equals(Object object) {
        if (this == object) {
            return true;
        }
        if (object instanceof DefaultTunnelTerminationPoint) {
            DefaultTunnelTerminationPoint that = (DefaultTunnelTerminationPoint) object;
            return Objects.equal(ttpId, that.ttpId) &&
                    Objects.equal(switchingLayer, that.switchingLayer) &&
                    Objects.equal(encodingLayer, that.encodingLayer) &&
                    Objects.equal(flags, that.flags) &&
                    Objects.equal(interLayerLockList, that.interLayerLockList) &&
                    Objects.equal(localLinkConnectivityList, that.localLinkConnectivityList) &&
                    Objects.equal(availAdaptBandwidth, that.availAdaptBandwidth);
        }
        return false;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this)
                .add("ttpId", ttpId)
                .add("switchingLayer", switchingLayer)
                .add("encodingLayer", encodingLayer)
                .add("flags", flags)
                .add("interLayerLockList", interLayerLockList)
                .add("localLinkConnectivityList", localLinkConnectivityList)
                .add("availAdaptBandwidth", availAdaptBandwidth)
                .toString();
    }
}
