/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.onlab.onos.optical.cfg;

import static org.onlab.onos.net.DeviceId.deviceId;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

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.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.DefaultAnnotations;
import org.onlab.onos.net.Device;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.Link;
import org.onlab.onos.net.MastershipRole;
import org.onlab.onos.net.PortNumber;
import org.onlab.onos.net.device.DefaultDeviceDescription;
import org.onlab.onos.net.device.DeviceDescription;
import org.onlab.onos.net.device.DeviceProvider;
import org.onlab.onos.net.device.DeviceProviderRegistry;
import org.onlab.onos.net.device.DeviceProviderService;
import org.onlab.onos.net.link.DefaultLinkDescription;
import org.onlab.onos.net.link.LinkProvider;
import org.onlab.onos.net.link.LinkProviderRegistry;
import org.onlab.onos.net.link.LinkProviderService;
import org.onlab.onos.net.provider.AbstractProvider;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.packet.ChassisId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * OpticalConfigProvider emulates the SB network provider for optical switches,
 * optical links and any other state that needs to be configured for correct network
 * operations.
 *
 */

@JsonIgnoreProperties(ignoreUnknown = true)
@Component(immediate = true)
public class OpticalConfigProvider extends AbstractProvider implements DeviceProvider, LinkProvider {

    protected static final Logger log = LoggerFactory
            .getLogger(OpticalConfigProvider.class);

    // TODO: fix hard coded file path later.
    private static final String DEFAULT_CONFIG_FILE =
            "/opt/onos/config/demo-3-roadm-2-ps.json";
    private String configFileName = DEFAULT_CONFIG_FILE;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected LinkProviderRegistry linkProviderRegistry;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected DeviceProviderRegistry deviceProviderRegistry;

    private static final String OPTICAL_ANNOTATION = "optical.";

    private LinkProviderService linkProviderService;
    private DeviceProviderService deviceProviderService;

    private static final List<Roadm> RAW_ROADMS = new ArrayList<>();
    private static final List<WdmLink> RAW_WDMLINKS = new ArrayList<>();
    private static final List<PktOptLink> RAW_PKTOPTLINKS = new ArrayList<>();

    private static final String ROADM = "Roadm";
    private static final String WDM_LINK = "wdmLink";
    private static final String PKT_OPT_LINK = "pktOptLink";

    protected OpticalNetworkConfig opticalNetworkConfig;

    public OpticalConfigProvider() {
        super(new ProviderId("optical", "org.onlab.onos.provider" +
                ".opticalConfig"));
    }

    @Activate
    protected void activate() {
        linkProviderService = linkProviderRegistry.register(this);
        deviceProviderService = deviceProviderRegistry.register(this);
        log.info("Starting optical network configuration process...");
        log.info("Optical config file set to {}", configFileName);

        loadOpticalConfig();
        parseOpticalConfig();
        publishOpticalConfig();
    }

    @Deactivate
    protected void deactivate() {
        linkProviderRegistry.unregister(this);
        linkProviderService = null;
        deviceProviderRegistry.unregister(this);
        deviceProviderService = null;
        RAW_ROADMS.clear();
        RAW_WDMLINKS.clear();
        RAW_PKTOPTLINKS.clear();
        log.info("Stopped");
    }

    private void loadOpticalConfig() {
        ObjectMapper mapper = new ObjectMapper();
        opticalNetworkConfig = new OpticalNetworkConfig();
        try {
            opticalNetworkConfig = mapper.readValue(new File(configFileName), OpticalNetworkConfig.class);
        } catch (JsonParseException e) {
            String err = String.format("JsonParseException while loading network "
                    + "config from file: %s: %s", configFileName, e.getMessage());
            log.error(err, e);
        } catch (JsonMappingException e) {
            String err = String.format(
                    "JsonMappingException while loading network config "
                            + "from file: %s: %s", configFileName, e.getMessage());
            log.error(err, e);
        } catch (IOException e) {
            String err = String.format("IOException while loading network config "
                    + "from file: %s %s", configFileName, e.getMessage());
            log.error(err, e);
        }
    }

    private void parseOpticalConfig() {
        List<OpticalSwitchDescription> swList = opticalNetworkConfig.getOpticalSwitches();
        List<OpticalLinkDescription> lkList = opticalNetworkConfig.getOpticalLinks();

        for (OpticalSwitchDescription sw : swList) {
            String swtype = sw.getType();
            boolean allow = sw.isAllowed();
           if (swtype.equals(ROADM) && allow) {
               int regNum = 0;
               Set<Map.Entry<String, JsonNode>> m = sw.params.entrySet();
               for (Map.Entry<String, JsonNode> e : m) {
                       String key = e.getKey();
                       JsonNode j = e.getValue();
                       if (key.equals("numRegen")) {
                           regNum = j.asInt();
                       }
                }

                Roadm newRoadm = new Roadm();
                newRoadm.setName(sw.name);
                newRoadm.setNodeId(sw.nodeDpid);
                newRoadm.setLongtitude(sw.longitude);
                newRoadm.setLatitude(sw.latitude);
                newRoadm.setRegenNum(regNum);

                RAW_ROADMS.add(newRoadm);
                log.info(newRoadm.toString());
            }
           }

        for (OpticalLinkDescription lk : lkList) {
            String lktype = lk.getType();
            switch (lktype) {
            case WDM_LINK:
                WdmLink newWdmLink = new WdmLink();
                newWdmLink.setSrcNodeId(lk.getNodeDpid1());
                newWdmLink.setSnkNodeId(lk.getNodeDpid2());
                newWdmLink.setAdminWeight(1000); // default weight for each WDM link.
                Set<Map.Entry<String, JsonNode>> m = lk.params.entrySet();
                for (Map.Entry<String, JsonNode> e : m) {
                    String key = e.getKey();
                    JsonNode j = e.getValue();
                    if (key.equals("nodeName1")) {
                        newWdmLink.setSrcNodeName(j.asText());
                    } else if (key.equals("nodeName2")) {
                        newWdmLink.setSnkNodeName(j.asText());
                    } else if (key.equals("port1")) {
                        newWdmLink.setSrcPort(j.asInt());
                    } else if (key.equals("port2")) {
                        newWdmLink.setSnkPort(j.asInt());
                    } else if (key.equals("distKms")) {
                        newWdmLink.setDistance(j.asDouble());
                    } else if (key.equals("numWaves")) {
                        newWdmLink.setWavelengthNumber(j.asInt());
                    } else {
                        log.error("error found");
                        // TODO add exception processing;
                    }
                }
                RAW_WDMLINKS.add(newWdmLink);
                log.info(newWdmLink.toString());

                break;

            case PKT_OPT_LINK:
                PktOptLink newPktOptLink = new PktOptLink();
                newPktOptLink.setSrcNodeId(lk.getNodeDpid1());
                newPktOptLink.setSnkNodeId(lk.getNodeDpid2());
                newPktOptLink.setAdminWeight(10); // default weight for each packet-optical link.
                Set<Map.Entry<String, JsonNode>> ptm = lk.params.entrySet();
                for (Map.Entry<String, JsonNode> e : ptm) {
                    String key = e.getKey();
                    JsonNode j = e.getValue();
                    if (key.equals("nodeName1")) {
                        newPktOptLink.setSrcNodeName(j.asText());
                    } else if (key.equals("nodeName2")) {
                        newPktOptLink.setSnkNodeName(j.asText());
                    } else if (key.equals("port1")) {
                        newPktOptLink.setSrcPort(j.asInt());
                    } else if (key.equals("port2")) {
                        newPktOptLink.setSnkPort(j.asInt());
                    } else if (key.equals("bandWidth")) {
                        newPktOptLink.setBandwdith(j.asDouble());
                    } else {
                        log.error("error found");
                        // TODO add exception processing;
                    }
                }

                RAW_PKTOPTLINKS.add(newPktOptLink);
                log.info(newPktOptLink.toString());
                break;
            default:
            }
        }
    }

    private void publishOpticalConfig() {
        if (deviceProviderService == null || linkProviderService == null) {
            return;
        }

        // Discover the optical ROADM objects
        Iterator<Roadm> iterWdmNode = RAW_ROADMS.iterator();
        while (iterWdmNode.hasNext()) {
            Roadm value = iterWdmNode.next();
            DeviceId did = deviceId("of:" + value.getNodeId().replace(":", ""));
            ChassisId cid = new ChassisId();
            DefaultAnnotations extendedAttributes = DefaultAnnotations.builder()
                    .set(OPTICAL_ANNOTATION + "switchType", "ROADM")
                    .set(OPTICAL_ANNOTATION + "switchName", value.getName())
                    .set(OPTICAL_ANNOTATION + "latitude", Double.toString(value.getLatitude()))
                    .set(OPTICAL_ANNOTATION + "longtitude", Double.toString(value.getLongtitude()))
                    .set(OPTICAL_ANNOTATION + "regNum", Integer.toString(value.getRegenNum()))
                    .build();

            DeviceDescription description =
                    new DefaultDeviceDescription(did.uri(),
                                                 Device.Type.SWITCH,
                                                 "",
                                                 "",
                                                 "",
                                                 "",
                                                 cid,
                                                 extendedAttributes);
            deviceProviderService.deviceConnected(did, description);
        }

        // Discover the optical WDM link objects
        Iterator<WdmLink> iterWdmlink = RAW_WDMLINKS.iterator();
        while (iterWdmlink.hasNext()) {
            WdmLink value = iterWdmlink.next();

            DeviceId srcNodeId = deviceId("of:" + value.getSrcNodeId().replace(":", ""));
            DeviceId snkNodeId = deviceId("of:" + value.getSnkNodeId().replace(":", ""));

            PortNumber srcPort = PortNumber.portNumber(value.getSrcPort());
            PortNumber snkPort = PortNumber.portNumber(value.getSnkPort());

            ConnectPoint srcPoint = new ConnectPoint(srcNodeId, srcPort);
            ConnectPoint snkPoint = new ConnectPoint(snkNodeId, snkPort);

            DefaultAnnotations extendedAttributes = DefaultAnnotations.builder()
                    .set(OPTICAL_ANNOTATION + "linkType", "WDM")
                    .set(OPTICAL_ANNOTATION + "distance", Double.toString(value.getDistance()))
                    .set(OPTICAL_ANNOTATION + "cost", Double.toString(value.getDistance()))
                    .set(OPTICAL_ANNOTATION + "adminWeight", Double.toString(value.getAdminWeight()))
                    .set(OPTICAL_ANNOTATION + "wavelengthNum", Integer.toString(value.getWavelengthNumber()))
                    .build();

            DefaultLinkDescription linkDescription =
                    new DefaultLinkDescription(srcPoint,
                                                 snkPoint,
                                                 Link.Type.OPTICAL,
                                                 extendedAttributes);

            linkProviderService.linkDetected(linkDescription);
            log.info(String.format("WDM link: %s : %s",
                    linkDescription.src().toString(), linkDescription.dst().toString()));


            DefaultLinkDescription linkDescriptionReverse =
                    new DefaultLinkDescription(snkPoint,
                                                 srcPoint,
                                                 Link.Type.OPTICAL,
                                                 extendedAttributes);

            linkProviderService.linkDetected(linkDescriptionReverse);
            log.info(String.format("WDM link: %s : %s",
                    linkDescriptionReverse.src().toString(), linkDescriptionReverse.dst().toString()));
        }

        // Discover the packet optical link objects
        Iterator<PktOptLink> iterPktOptlink = RAW_PKTOPTLINKS.iterator();
        while (iterPktOptlink.hasNext()) {
            PktOptLink value = iterPktOptlink.next();
            DeviceId srcNodeId = deviceId("of:" + value.getSrcNodeId().replace(":", ""));
            DeviceId snkNodeId = deviceId("of:" + value.getSnkNodeId().replace(":", ""));

            PortNumber srcPort = PortNumber.portNumber(value.getSrcPort());
            PortNumber snkPort = PortNumber.portNumber(value.getSnkPort());

            ConnectPoint srcPoint = new ConnectPoint(srcNodeId, srcPort);
            ConnectPoint snkPoint = new ConnectPoint(snkNodeId, snkPort);

            DefaultAnnotations extendedAttributes = DefaultAnnotations.builder()
                    .set(OPTICAL_ANNOTATION + "linkType", "PktOptLink")
                    .set(OPTICAL_ANNOTATION + "bandwidth", Double.toString(value.getBandwidth()))
                    .set(OPTICAL_ANNOTATION + "cost", Double.toString(value.getBandwidth()))
                    .set(OPTICAL_ANNOTATION + "adminWeight", Double.toString(value.getAdminWeight()))
                    .build();

            DefaultLinkDescription linkDescription =
                    new DefaultLinkDescription(srcPoint,
                                                 snkPoint,
                                                 Link.Type.OPTICAL,
                                                 extendedAttributes);

            linkProviderService.linkDetected(linkDescription);
            log.info(String.format("Packet-optical link: %s : %s",
                    linkDescription.src().toString(), linkDescription.dst().toString()));

            DefaultLinkDescription linkDescriptionReverse =
                    new DefaultLinkDescription(snkPoint,
                                                 srcPoint,
                                                 Link.Type.OPTICAL,
                                                 extendedAttributes);

            linkProviderService.linkDetected(linkDescriptionReverse);
            log.info(String.format("Packet-optical link: %s : %s",
                    linkDescriptionReverse.src().toString(), linkDescriptionReverse.dst().toString()));
        }

    }

    @Override
    public void triggerProbe(Device device) {
        // TODO We may want to consider re-reading config files and publishing them based on this event.
    }

    @Override
    public void roleChanged(Device device, MastershipRole newRole) {
        // TODO Auto-generated method stub.
    }

}
