/*
 * Copyright 2021-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.net.behaviour.upf;

import com.google.common.annotations.Beta;
import org.onlab.packet.Ip4Address;

import java.util.Objects;

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

/**
 * A structure representing the UE Termination in the uplink direction on the
 * UPF-programmable device.
 * Provide means to configure the traffic behavior (e.g. set Traffic Class).
 */
@Beta
public final class UpfTerminationUplink implements UpfEntity {
    // Match Keys
    private final Ip4Address ueSessionId; // UE Session ID, use UE IP address to uniquely identify a session.
    private final byte applicationId; // Application ID defaults to DEFAULT_APP_ID
    // Action parameters
    private final Integer ctrId;  // Counter ID unique to this UPF Termination Rule
    private final Byte trafficClass;
    private final int appMeterIdx;
    private final boolean dropping;

    private UpfTerminationUplink(Ip4Address ueSessionId, byte applicationId,
                                 Integer ctrId, Byte trafficClass,
                                 int appMeterIdx, boolean dropping) {
        this.ueSessionId = ueSessionId;
        this.applicationId = applicationId;
        this.ctrId = ctrId;
        this.trafficClass = trafficClass;
        this.appMeterIdx = appMeterIdx;
        this.dropping = dropping;
    }

    public static Builder builder() {
        return new Builder();
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        UpfTerminationUplink that = (UpfTerminationUplink) obj;

        // Safe comparisons between potentially null objects
        return this.dropping == that.dropping &&
                Objects.equals(this.ueSessionId, that.ueSessionId) &&
                Objects.equals(this.applicationId, that.applicationId) &&
                Objects.equals(this.ctrId, that.ctrId) &&
                this.appMeterIdx == that.appMeterIdx &&
                Objects.equals(this.trafficClass, that.trafficClass);
    }

    @Override
    public int hashCode() {
        return Objects.hash(ueSessionId, applicationId, ctrId, trafficClass, appMeterIdx, dropping);
    }

    /**
     * Get UE Session ID associated with UPF Termination rule.
     *
     * @return UE Session ID
     */
    public Ip4Address ueSessionId() {
        return ueSessionId;
    }

    /**
     * Get the application ID associated with UPF Termination rule.
     *
     * @return Application ID
     */
    public byte applicationId() {
        return applicationId;
    }

    /**
     * Get PDR Counter ID associated with UPF Termination rule.
     *
     * @return PDR counter cell ID
     */
    public Integer counterId() {
        return ctrId;
    }

    /**
     * Get Traffic Class set by this UPF Termination rule.
     *
     * @return Traffic Class
     */
    public Byte trafficClass() {
        return trafficClass;
    }

    /**
     * True if this UPF Termination needs to drop traffic.
     *
     * @return true if the UPF Termination needs dropping.
     */
    public boolean needsDropping() {
        return dropping;
    }

    /**
     * Get the app meter index set by this UPF Termination rule.
     *
     * @return App meter index
     */
    public int appMeterIdx() {
        return appMeterIdx;
    }

    @Override
    public UpfEntityType type() {
        return UpfEntityType.TERMINATION_UPLINK;
    }

    @Override
    public String toString() {
        return "UpfTerminationUL(" + matchString() + " -> " + actionString() + ")";
    }

    private String matchString() {
        return "Match(ue_addr=" + this.ueSessionId() + ", app_id=" + this.applicationId() + ")";
    }

    private String actionString() {
        String fwd = "FWD";
        if (this.needsDropping()) {
            fwd = "DROP";
        }
        return "Action(" + fwd +
                ", ctr_id=" + this.counterId() +
                ", tc=" + this.trafficClass() +
                ", app_meter_idx=" + this.appMeterIdx() +
                ")";
    }

    public static class Builder {
        private Ip4Address ueSessionId = null;
        private Byte applicationId = null;
        private Integer ctrId = null;
        private Byte trafficClass = null;
        private int appMeterIdx = DEFAULT_APP_INDEX;
        private boolean dropping = false;

        public Builder() {

        }

        /**
         * Set the ID of the UE session.
         *
         * @param ueSessionId UE session ID
         * @return This builder object
         */
        public Builder withUeSessionId(Ip4Address ueSessionId) {
            this.ueSessionId = ueSessionId;
            return this;
        }

        /**
         * Set the ID of the application.
         * If not set, default to {@link UpfEntity#DEFAULT_APP_ID}.
         *
         * @param applicationId Application ID
         * @return This builder object
         */
        public Builder withApplicationId(byte applicationId) {
            this.applicationId = applicationId;
            return this;
        }

        /**
         * Set the dataplane counter cell ID.
         *
         * @param ctrId PDR counter cell ID
         * @return This builder object
         */
        public Builder withCounterId(int ctrId) {
            this.ctrId = ctrId;
            return this;
        }

        /**
         * Set the Traffic Class.
         *
         * @param trafficClass Traffic Class
         * @return This builder object
         */
        public Builder withTrafficClass(byte trafficClass) {
            this.trafficClass = trafficClass;
            return this;
        }

        /**
         * Sets whether to drop uplink UPF termination traffic or not.
         *
         * @param dropping True if request to drop, false otherwise
         * @return This builder object
         */
        public Builder needsDropping(boolean dropping) {
            this.dropping = dropping;
            return this;
        }

        /**
         * Sets the app meter index.
         * If not set, default to {@link UpfEntity#DEFAULT_APP_INDEX}.
         *
         * @param appMeterIdx App meter index
         * @return This builder object
         */
        public Builder withAppMeterIdx(int appMeterIdx) {
            this.appMeterIdx = appMeterIdx;
            return this;
        }

        public UpfTerminationUplink build() {
            // Match fields must be provided
            checkNotNull(ueSessionId, "UE session ID must be provided");
            if (applicationId == null) {
                applicationId = DEFAULT_APP_ID;
            }
            checkNotNull(ctrId, "Counter ID must be provided");
            // TODO: should we verify that when dropping no other fields are provided
            return new UpfTerminationUplink(
                    this.ueSessionId, this.applicationId, this.ctrId,
                    this.trafficClass, this.appMeterIdx, this.dropping
            );
        }

    }

}
