/*
 * Copyright 2016-present 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.sdxl2;

import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.Key;
import org.onosproject.net.intent.PointToPointIntent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

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

/**
 * Manages Virtual Circuits using MAC addresses.
 */
public class SdxL2MacVCManager extends SdxL2VCManager {

    private static final int PRIORITY_OFFSET = 2000;
    private static Logger log = LoggerFactory.getLogger(SdxL2MacVCManager.class);

    private static String errorMacNull = "VC cannot be %s: the mac address of %s is null";
    private static String errorMacEqual = "VC cannot be %s: same mac addresses on both sides";

    /**
     * Creates an SDX-L2 MAC VC Manager.
     *
     * @param sdxl2id application ID
     * @param store reference to the SDX-L2 store
     * @param intentService reference to the Intent service
     */
    public SdxL2MacVCManager(ApplicationId sdxl2id,
                             SdxL2Store store,
                             IntentService intentService) {
        super(sdxl2id, store, intentService);
        log.info("Started");
    }

    @Override
    public Collection<Intent> buildIntents(String sdxl2, SdxL2ConnectionPoint ingress, SdxL2ConnectionPoint egress) {
        List<Intent> intents = null;
        TrafficSelector selector;
        TrafficTreatment treatment;
        Key key;

        if (ingress.vlanIds().size() == egress.vlanIds().size()) {
            intents = new ArrayList<Intent>();
            if (ingress.vlanIds().size() == 0) {
                selector = buildSelector(ingress.macAddress(),
                                         egress.macAddress(),
                                         null,
                                         null);
                treatment = DefaultTrafficTreatment.emptyTreatment();
                key = generateIntentKey(sdxl2, ingress, egress, "1");

                intents.add(PointToPointIntent.builder()
                                    .appId(appId)
                                    .key(key)
                                    .selector(selector)
                                    .treatment(treatment)

                                    .ingressPoint(ingress.connectPoint())
                                    .egressPoint(egress.connectPoint())
                                    .priority(PRIORITY_OFFSET)
                                    .build());
            } else {
                Iterator<VlanId> ingressTags = ingress.vlanIds().iterator();
                Iterator<VlanId> egressTags = egress.vlanIds().iterator();
                int index = 1;
                while (ingressTags.hasNext()) {
                    selector = buildSelector(ingress.macAddress(),
                                             egress.macAddress(),
                                             null,
                                             ingressTags.next());
                    treatment = buildTreatment(egressTags.next(),
                                               null,
                                               false);
                    key = generateIntentKey(sdxl2, ingress, egress, String.valueOf(index));

                    intents.add(PointToPointIntent.builder()
                                        .appId(appId)
                                        .key(key)
                                        .selector(selector)
                                        .treatment(treatment)
                                        .ingressPoint(ingress.connectPoint())
                                        .egressPoint(egress.connectPoint())
                                        .priority(PRIORITY_OFFSET)
                                        .build());
                    index = index + 1;
                }
            }
            return intents;
        }

        if (ingress.vlanIds().size() == 1 && egress.vlanIds().size() == 0) {
            Iterator<VlanId> ingressTags = ingress.vlanIds().iterator();
            intents = new ArrayList<Intent>();
            selector = buildSelector(ingress.macAddress(),
                                     egress.macAddress(),
                                     null,
                                     ingressTags.next());
            treatment = buildTreatment(null,
                                       null,
                                       true);
            key = generateIntentKey(sdxl2, ingress, egress, "1");

            intents.add(PointToPointIntent.builder()
                                .appId(appId)
                                .key(key)
                                .selector(selector)
                                .treatment(treatment)
                                .ingressPoint(ingress.connectPoint())
                                .egressPoint(egress.connectPoint())
                                .priority(PRIORITY_OFFSET)
                                .build());
            return intents;
        }

        if (ingress.vlanIds().size() == 0 && egress.vlanIds().size() == 1) {
            Iterator<VlanId> egressTags = egress.vlanIds().iterator();
            intents = new ArrayList<Intent>();
            selector = buildSelector(ingress.macAddress(),
                                     egress.macAddress(),
                                     null,
                                     null);
            treatment = buildTreatment(null,
                                       egressTags.next(),
                                       false);
            key = generateIntentKey(sdxl2, ingress, egress, "1");

            intents.add(PointToPointIntent.builder()
                                .appId(appId)
                                .key(key)
                                .selector(selector)
                                .treatment(treatment)
                                .ingressPoint(ingress.connectPoint())
                                .egressPoint(egress.connectPoint())
                                .priority(PRIORITY_OFFSET)
                                .build());
            return intents;
        }

        log.warn(String.format(errorCreateIntents, ingress.name(), egress.name()));

        return intents;
    }

    @Override
    public void addVC(String sdxl2, SdxL2ConnectionPoint sdxl2cplhs, SdxL2ConnectionPoint sdxl2cprhs) {
        String action = "created";
        checkState(!(isNullMac(sdxl2cplhs.macAddress()) && isNullMac(sdxl2cprhs.macAddress())),
                   errorMacNull, action, sdxl2cplhs.name() + " and " + sdxl2cprhs.name());
        checkState(!isNullMac(sdxl2cprhs.macAddress()), errorMacNull, action, sdxl2cplhs.name());
        checkState(!isNullMac(sdxl2cprhs.macAddress()), errorMacNull, action, sdxl2cprhs.name());
        checkState(!sdxl2cplhs.macAddress().equals(sdxl2cprhs.macAddress()), errorMacEqual, action);
        super.addVC(sdxl2, sdxl2cplhs, sdxl2cprhs);
    }

    @Override
    public void removeVC(SdxL2ConnectionPoint sdxl2cplhs, SdxL2ConnectionPoint sdxl2cprhs) {
        String action = "deleted";
        checkState(!(isNullMac(sdxl2cplhs.macAddress()) && isNullMac(sdxl2cprhs.macAddress())),
                   errorMacNull, action, sdxl2cplhs.name() + " and " + sdxl2cprhs.name());
        checkState(!sdxl2cplhs.macAddress().equals(MacAddress.ZERO), errorMacNull, action, sdxl2cplhs.name());
        checkState(!sdxl2cprhs.macAddress().equals(MacAddress.ZERO), errorMacNull, action, sdxl2cprhs.name());
        checkState(!sdxl2cplhs.macAddress().equals(sdxl2cprhs.macAddress()), errorMacEqual, action);
        super.removeVC(sdxl2cplhs, sdxl2cprhs);
    }

    @Override
    public void removeVC(SdxL2ConnectionPoint cp) {
        checkState(!cp.macAddress().equals(MacAddress.ZERO), errorMacNull, "deleted", cp.name());
        super.removeVC(cp);
    }

    private boolean isNullMac(MacAddress mac) {
        return mac.equals(MacAddress.ZERO);
    }

    private TrafficSelector buildSelector(MacAddress ingressMac,
                                          MacAddress egressMac,
                                          Short ethertype,
                                          VlanId ingresstag) {

        TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
        selectorBuilder.matchEthSrc(ingressMac);
        selectorBuilder.matchEthDst(egressMac);
        if (ethertype != null) {
            selectorBuilder.matchEthType(ethertype);
        }
        if (ingresstag != null) {
            selectorBuilder.matchVlanId(ingresstag);
        }
        return selectorBuilder.build();
    }

}
