/*
 * 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.provider.lldp.impl;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;

import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.slf4j.Logger;

import java.io.File;
import java.io.IOException;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/*
 * JSON file example
 *

{
  "deviceId" : [ "of:2222000000000000" ],
  "deviceType" : [ "ROADM" ],
  "annotation" : { "no-lldp" : null, "sendLLDP" : "false" }
}
 */

/**
 * Allows for reading and writing LLDP suppression definition as a JSON file.
 */
public class SuppressionRulesStore {

    private static final String DEVICE_ID = "deviceId";
    private static final String DEVICE_TYPE = "deviceType";
    private static final String ANNOTATION = "annotation";

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

    private final File file;

    /**
     * Creates a reader/writer of the LLDP suppression definition file.
     *
     * @param filePath location of the definition file
     */
    public SuppressionRulesStore(String filePath) {
        file = new File(filePath);
    }

    /**
     * Creates a reader/writer of the LLDP suppression definition file.
     *
     * @param file definition file
     */
    public SuppressionRulesStore(File file) {
        this.file = checkNotNull(file);
    }

    /**
     * Returns SuppressionRules.
     *
     * @return SuppressionRules
     * @throws IOException
     */
    public SuppressionRules read() throws IOException {
        final Set<DeviceId> suppressedDevice = new HashSet<>();
        final EnumSet<Device.Type> suppressedDeviceType = EnumSet.noneOf(Device.Type.class);
        final Map<String, String> suppressedAnnotation = new HashMap<>();

        ObjectMapper mapper = new ObjectMapper();
        ObjectNode root = (ObjectNode) mapper.readTree(file);

        for (JsonNode deviceId : root.get(DEVICE_ID)) {
            if (deviceId.isTextual()) {
                suppressedDevice.add(DeviceId.deviceId(deviceId.asText()));
            } else {
                log.warn("Encountered unexpected JSONNode {} for deviceId", deviceId);
            }
        }

        for (JsonNode deviceType : root.get(DEVICE_TYPE)) {
            if (deviceType.isTextual()) {
                suppressedDeviceType.add(Device.Type.valueOf(deviceType.asText()));
            } else {
                log.warn("Encountered unexpected JSONNode {} for deviceType", deviceType);
            }
        }

        JsonNode annotation = root.get(ANNOTATION);
        if (annotation.isObject()) {
            ObjectNode obj = (ObjectNode) annotation;
            Iterator<Entry<String, JsonNode>> it = obj.fields();
            while (it.hasNext()) {
                Entry<String, JsonNode> entry = it.next();
                final String key = entry.getKey();
                final JsonNode value = entry.getValue();

                if (value.isValueNode()) {
                    if (value.isNull()) {
                        suppressedAnnotation.put(key, SuppressionRules.ANY_VALUE);
                    } else {
                        suppressedAnnotation.put(key, value.asText());
                    }
                } else {
                    log.warn("Encountered unexpected JSON field {} for annotation", entry);
                }
            }
        } else {
            log.warn("Encountered unexpected JSONNode {} for annotation", annotation);
        }

        return new SuppressionRules(suppressedDevice,
                                    suppressedDeviceType,
                                    suppressedAnnotation);
    }

    /**
     * Writes the given SuppressionRules.
     *
     * @param rules SuppressionRules
     * @throws IOException
     */
    public void write(SuppressionRules rules) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        ObjectNode root = mapper.createObjectNode();
        ArrayNode deviceIds = mapper.createArrayNode();
        ArrayNode deviceTypes = mapper.createArrayNode();
        ObjectNode annotations = mapper.createObjectNode();
        root.set(DEVICE_ID, deviceIds);
        root.set(DEVICE_TYPE, deviceTypes);
        root.set(ANNOTATION, annotations);

        rules.getSuppressedDevice()
            .forEach(deviceId -> deviceIds.add(deviceId.toString()));

        rules.getSuppressedDeviceType()
            .forEach(type -> deviceTypes.add(type.toString()));

        rules.getSuppressedAnnotation().forEach((key, value) -> {
            if (value == SuppressionRules.ANY_VALUE) {
                annotations.putNull(key);
            } else {
                annotations.put(key, value);
            }
        });
        mapper.writeTree(new JsonFactory().createGenerator(file, JsonEncoding.UTF8),
                         root);
    }
}
