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

import com.google.common.annotations.Beta;
import com.google.common.collect.ImmutableList;

import java.util.Objects;
import java.util.Optional;

/**
 * ResourceId for {@link ContinuousResource}.
 */
@Beta
public final class ContinuousResourceId extends ResourceId {
    private final ImmutableList<Object> components;

    // for printing purpose only (used in toString() implementation)
    private final String name;

    ContinuousResourceId(ImmutableList.Builder<Object> parentComponents, Class<?> last) {
        this.components = parentComponents.add(last.getCanonicalName()).build();
        this.name = last.getSimpleName();
    }

    // for serializer
    ContinuousResourceId() {
        this.components = ImmutableList.of();
        this.name = "";
    }

    @Override
    ImmutableList<Object> components() {
        return components;
    }

    /**
     * {@inheritDoc}
     *
     * A child of a continuous-type resource is prohibited.
     * {@link UnsupportedOperationException} is always thrown.
     */
    @Override
    public DiscreteResourceId child(Object child) {
        throw new UnsupportedOperationException();
    }

    /**
     * {@inheritDoc}
     *
     * A child of a continuous-type resource is prohibited.
     * {@link UnsupportedOperationException} is always thrown.
     */
    @Override
    public ContinuousResourceId child(Class<?> child) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Optional<DiscreteResourceId> parent() {
        if (components.size() == 0) {
            return Optional.empty();
        }
        if (components.size() == 1) {
            return Optional.of(ROOT);
        } else {
            return Optional.of(new DiscreteResourceId(components.subList(0, components.size() - 1)));
        }
    }

    @Override
    public int hashCode() {
        return components.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        final ContinuousResourceId other = (ContinuousResourceId) obj;
        return Objects.equals(this.components, other.components);
    }

    @Override
    public String toString() {
        // due to performance consideration, the value might need to be stored in a field
        return ImmutableList.builder()
                .addAll(components.subList(0, components.size() - 1))
                .add(name)
                .build().toString();
    }
}
