/*
 * Copyright 2015 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.segmentrouting;

import org.onlab.packet.Ethernet;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.TpPort;
import org.onosproject.cli.net.IpProtocol;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flowobjective.DefaultForwardingObjective;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.segmentrouting.config.DeviceConfiguration;
import org.onosproject.store.service.EventuallyConsistentMap;
import org.slf4j.Logger;

import java.util.List;
import java.util.stream.Collectors;

import static org.slf4j.LoggerFactory.getLogger;

/**
 * Segment Routing Policy Handler.
 */
public class PolicyHandler {

    protected final Logger log = getLogger(getClass());

    private ApplicationId appId;
    private DeviceConfiguration deviceConfiguration;
    private FlowObjectiveService flowObjectiveService;
    private TunnelHandler tunnelHandler;
    private final EventuallyConsistentMap<String, Policy> policyStore;

    public enum Result {
        SUCCESS,
        POLICY_EXISTS,
        ID_EXISTS,
        TUNNEL_NOT_FOUND,
        POLICY_NOT_FOUND,
        UNSUPPORTED_TYPE
    }

    /**
     * Creates a reference.
     *
     * @param appId                segment routing application ID
     * @param deviceConfiguration  DeviceConfiguration reference
     * @param flowObjectiveService FlowObjectiveService reference
     * @param tunnelHandler        tunnel handler reference
     * @param policyStore          policy store
     */
    public PolicyHandler(ApplicationId appId,
                         DeviceConfiguration deviceConfiguration,
                         FlowObjectiveService flowObjectiveService,
                         TunnelHandler tunnelHandler,
                         EventuallyConsistentMap<String, Policy> policyStore) {
        this.appId = appId;
        this.deviceConfiguration = deviceConfiguration;
        this.flowObjectiveService = flowObjectiveService;
        this.tunnelHandler = tunnelHandler;
        this.policyStore = policyStore;
    }

    /**
     * Returns the policies.
     *
     * @return policy list
     */
    public List<Policy> getPolicies() {
        return policyStore.values()
                .stream()
                .filter(policy -> policy instanceof TunnelPolicy)
                .map(policy -> new TunnelPolicy((TunnelPolicy) policy))
                .collect(Collectors.toList());
    }

    /**
     * Creates a policy using the policy information given.
     *  @param policy policy reference to create
     *  @return ID_EXISTS if the same policy ID exists,
     *  POLICY_EXISTS if the same policy exists, TUNNEL_NOT_FOUND if the tunnel
     *  does not exists, UNSUPPORTED_TYPE if the policy type is not supported,
     *  SUCCESS if the policy is created successfully
     */
    public Result createPolicy(Policy policy) {

        if (policyStore.containsKey(policy.id())) {
            log.warn("The policy id {} exists already", policy.id());
            return Result.ID_EXISTS;
        }

        if (policyStore.containsValue(policy)) {
            log.warn("The same policy exists already");
            return Result.POLICY_EXISTS;
        }

        if (policy.type() == Policy.Type.TUNNEL_FLOW) {

            TunnelPolicy tunnelPolicy = (TunnelPolicy) policy;
            Tunnel tunnel = tunnelHandler.getTunnel(tunnelPolicy.tunnelId());
            if (tunnel == null) {
                return Result.TUNNEL_NOT_FOUND;
            }

            ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
                    .builder()
                    .fromApp(appId)
                    .makePermanent()
                    .nextStep(tunnel.groupId())
                    .withPriority(tunnelPolicy.priority())
                    .withSelector(buildSelector(policy))
                    .withFlag(ForwardingObjective.Flag.VERSATILE);

            DeviceId source = deviceConfiguration.getDeviceId(tunnel.labelIds().get(0));
            flowObjectiveService.forward(source, fwdBuilder.add());

        } else {
            log.warn("Policy type {} is not supported yet.", policy.type());
            return Result.UNSUPPORTED_TYPE;
        }

        policyStore.put(policy.id(), policy);

        return Result.SUCCESS;
    }

    /**
     * Removes the policy given.
     *
     * @param policyInfo policy information to remove
     * @return POLICY_NOT_FOUND if the policy to remove does not exists,
     * SUCCESS if it is removed successfully
     */
    public Result removePolicy(Policy policyInfo) {

        if (policyStore.get(policyInfo.id()) != null) {
            Policy policy = policyStore.get(policyInfo.id());
            if (policy.type() == Policy.Type.TUNNEL_FLOW) {
                TunnelPolicy tunnelPolicy = (TunnelPolicy) policy;
                Tunnel tunnel = tunnelHandler.getTunnel(tunnelPolicy.tunnelId());

                ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
                        .builder()
                        .fromApp(appId)
                        .makePermanent()
                        .withSelector(buildSelector(policy))
                        .withPriority(tunnelPolicy.priority())
                        .nextStep(tunnel.groupId())
                        .withFlag(ForwardingObjective.Flag.VERSATILE);

                DeviceId source = deviceConfiguration.getDeviceId(tunnel.labelIds().get(0));
                flowObjectiveService.forward(source, fwdBuilder.remove());

                policyStore.remove(policyInfo.id());
            }
        } else {
            log.warn("Policy {} was not found", policyInfo.id());
            return Result.POLICY_NOT_FOUND;
        }

        return Result.SUCCESS;
    }


    private TrafficSelector buildSelector(Policy policy) {

        TrafficSelector.Builder tsb = DefaultTrafficSelector.builder();
        tsb.matchEthType(Ethernet.TYPE_IPV4);
        if (policy.dstIp() != null && !policy.dstIp().isEmpty()) {
            tsb.matchIPDst(IpPrefix.valueOf(policy.dstIp()));
        }
        if (policy.srcIp() != null && !policy.srcIp().isEmpty()) {
            tsb.matchIPSrc(IpPrefix.valueOf(policy.srcIp()));
        }
        if (policy.ipProto() != null && !policy.ipProto().isEmpty()) {
            Short ipProto = IpProtocol.valueOf(policy.ipProto()).value();
            tsb.matchIPProtocol(ipProto.byteValue());
            if (IpProtocol.valueOf(policy.ipProto()).equals(IpProtocol.TCP)) {
                if (policy.srcPort() != 0) {
                    tsb.matchTcpSrc(TpPort.tpPort(policy.srcPort()));
                }
                if (policy.dstPort() != 0) {
                    tsb.matchTcpDst(TpPort.tpPort(policy.dstPort()));
                }
            } else if (IpProtocol.valueOf(policy.ipProto()).equals(IpProtocol.UDP)) {
                if (policy.srcPort() != 0) {
                    tsb.matchUdpSrc(TpPort.tpPort(policy.srcPort()));
                }
                if (policy.dstPort() != 0) {
                    tsb.matchUdpDst(TpPort.tpPort(policy.dstPort()));
                }
            }
        }

        return tsb.build();
    }

}
