/*
 * Copyright 2014 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.olt;


import com.google.common.base.Strings;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Modified;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.VlanId;
import org.onlab.util.Tools;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
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.flowobjective.DefaultForwardingObjective;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;

import java.util.Dictionary;

import static org.slf4j.LoggerFactory.getLogger;

/**
 * Sample mobility application. Cleans up flowmods when a host moves.
 */
@Component(immediate = true)
public class OLT {

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected FlowObjectiveService flowObjectiveService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected DeviceService deviceService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected CoreService coreService;

    private final DeviceListener deviceListener = new InternalDeviceListener();

    private ApplicationId appId;

    public static final int OFFSET = 200;

    public static final int UPLINK_PORT = 129;

    public static final String OLT_DEVICE = "of:90e2ba82f97791e9";
    public static final String GFAST_DEVICE = "of:0011223344551357";

    @Property(name = "uplinkPort", intValue = UPLINK_PORT,
            label = "The OLT's uplink port number")
    private int uplinkPort = UPLINK_PORT;

    //TODO: replace this with an annotation lookup
    @Property(name = "oltDevice", value = OLT_DEVICE,
            label = "The OLT device id")
    private String oltDevice = OLT_DEVICE;

    @Property(name = "gfastDevice", value = GFAST_DEVICE,
            label = "The gfast device id")
    private String gfastDevice = GFAST_DEVICE;


    @Activate
    public void activate() {
        appId = coreService.registerApplication("org.onosproject.olt");

        deviceService.getPorts(DeviceId.deviceId(oltDevice)).stream().forEach(
                port -> {
                    if (port.isEnabled()) {
                        short vlanId = fetchVlanId(port.number());
                        provisionVlanOnPort(port.number(), (short) 7);
                        provisionVlanOnPort(port.number(), vlanId);
                    }
                }
        );


        deviceService.getPorts(DeviceId.deviceId(gfastDevice)).stream().forEach(
                port -> {
                    if (port.isEnabled()) {
                        short vlanId = (short) (fetchVlanId(port.number()) + OFFSET);
                        provisionVlanOnPort(port.number(), vlanId);
                    }
                }
        );
        log.info("Started with Application ID {}", appId.id());
    }

    @Deactivate
    public void deactivate() {
        log.info("Stopped");
    }

    @Modified
    public void modified(ComponentContext context) {
        Dictionary<?, ?> properties = context.getProperties();


        String s = Tools.get(properties, "uplinkPort");
        uplinkPort = Strings.isNullOrEmpty(s) ? UPLINK_PORT : Integer.parseInt(s);

        s = Tools.get(properties, "oltDevice");
        oltDevice = Strings.isNullOrEmpty(s) ? OLT_DEVICE : s;

    }


    private short fetchVlanId(PortNumber port) {
        long p = port.toLong() + OFFSET;
        if (p > 4095) {
            log.warn("Port Number {} exceeds vlan max", port);
            return -1;
        }
        return (short) p;
    }


    private void provisionVlanOnPort(PortNumber p, short vlanId) {


        TrafficSelector upstream = DefaultTrafficSelector.builder()
                .matchVlanId(VlanId.vlanId(vlanId))
                .matchInPort(p)
                .build();

        TrafficSelector downStream = DefaultTrafficSelector.builder()
                .matchVlanId(VlanId.vlanId(vlanId))
                .matchInPort(PortNumber.portNumber(uplinkPort))
                .build();

        TrafficTreatment upstreamTreatment = DefaultTrafficTreatment.builder()
                .setOutput(PortNumber.portNumber(uplinkPort))
                .build();

        TrafficTreatment downStreamTreatment = DefaultTrafficTreatment.builder()
                .setOutput(p)
                .build();


        ForwardingObjective upFwd = DefaultForwardingObjective.builder()
                .withFlag(ForwardingObjective.Flag.VERSATILE)
                .withPriority(1000)
                .makePermanent()
                .withSelector(upstream)
                .fromApp(appId)
                .withTreatment(upstreamTreatment)
                .add();

        ForwardingObjective downFwd = DefaultForwardingObjective.builder()
                .withFlag(ForwardingObjective.Flag.VERSATILE)
                .withPriority(1000)
                .makePermanent()
                .withSelector(downStream)
                .fromApp(appId)
                .withTreatment(downStreamTreatment)
                .add();

        flowObjectiveService.forward(DeviceId.deviceId(oltDevice), upFwd);
        flowObjectiveService.forward(DeviceId.deviceId(oltDevice), downFwd);

    }

    private class InternalDeviceListener implements DeviceListener {
        @Override
        public void event(DeviceEvent event) {
            DeviceId devId = DeviceId.deviceId(oltDevice);
            switch (event.type()) {
                case PORT_ADDED:
                case PORT_UPDATED:
                    if (devId.equals(event.subject().id()) && event.port().isEnabled()) {
                        short vlanId = fetchVlanId(event.port().number());
                        provisionVlanOnPort(event.port().number(), vlanId);
                    }
                    break;
                case DEVICE_ADDED:
                case DEVICE_UPDATED:
                case DEVICE_REMOVED:
                case DEVICE_SUSPENDED:
                case DEVICE_AVAILABILITY_CHANGED:
                case PORT_REMOVED:
                case PORT_STATS_UPDATED:
                default:
                    return;
            }
        }
    }


}


