/*
 * 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.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 =
            "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(DeviceId device, MastershipRole newRole) {
        // TODO Auto-generated method stub.
    }

    @Override
    public boolean isReachable(DeviceId device) {
        return false;
    }
}
