/*
 * Copyright 2017-present Open Networking Foundation
 *
 * 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.bmv2.model;

import com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonArray;
import com.eclipsesource.json.JsonObject;
import com.eclipsesource.json.JsonValue;
import com.google.common.annotations.Beta;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.onosproject.net.pi.model.PiMatchType;
import org.slf4j.Logger;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.Set;

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

/**
 * BMv2 pipeline model parser.
 *
 * @see <a href="https://github.com/p4lang/behavioral-model/blob/master/docs/JSON_format.md"> BMv2 JSON
 * specification</a>
 */
@Beta
public final class Bmv2PipelineModelParser {
    private static final Logger log = getLogger(Bmv2PipelineModelParser.class);

    // General fields and values
    private static final String NAME = "name";
    private static final String ID = "id";
    private static final int NO_ID = Integer.MIN_VALUE;

    // Hide default parser
    private Bmv2PipelineModelParser() {
    }

    /**
     * Parse the given JSON object representing a BMv2 configuration, to a Bmv2PipelineModel object.
     *
     * @param jsonObject the BMv2 json config
     * @return Bmv2PipelineModel BMv2 pipeline model object
     */
    public static Bmv2PipelineModel parse(JsonObject jsonObject) {
        List<Bmv2HeaderTypeModel> headerTypeModels = HeaderTypesParser.parse(jsonObject);
        Map<Integer, Integer> headerIdToIndex = HeaderStackParser.parse(jsonObject);
        List<Bmv2HeaderModel> headerModels = HeadersParser.parse(jsonObject, headerTypeModels, headerIdToIndex);
        List<Bmv2ActionModel> actionModels = ActionsParser.parse(jsonObject);
        List<Bmv2TableModel> tableModels = TablesParser.parse(jsonObject, headerModels, actionModels);

        return new Bmv2PipelineModel(headerTypeModels, headerModels,
                                     actionModels, tableModels);
    }

    /**
     * Parse the input stream pointing to a BMv2 JSON configuration, to a Bmv2PipelineModel object.
     *
     * @param url URL pointing to a BMv2 JSON configuration
     * @return Bmv2PipelineModel BMv2 pipeline model object
     */
    public static Bmv2PipelineModel parse(URL url) {
        checkNotNull(url, "Url cannot be null");
        try {
            InputStream inputStream = url.openStream();
            checkArgument(inputStream.available() > 0, "Empty or non-existent JSON at " + url.toString());
            return parse(Json.parse(new BufferedReader(
                    new InputStreamReader(inputStream))).asObject());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Parser for BMv2 header types.
     */
    private static class HeaderTypesParser {
        private static final String HEADER_TYPES = "header_types";
        private static final String FIELDS = "fields";
        private static final int FIELD_NAME_INDEX = 0;
        private static final int FIELD_BIT_WIDTH_INDEX = 1;
        private static final int FIELD_SIGNED_INDEX = 2;
        private static final int SIZE_WITH_SIGNED_FLAG = 3;

        private static List<Bmv2HeaderTypeModel> parse(JsonObject jsonObject) {
            List<Bmv2HeaderTypeModel> headerTypeModels = Lists.newArrayList();
            jsonObject.get(HEADER_TYPES).asArray().forEach(jsonValue -> {
                JsonObject headerFieldType = jsonValue.asObject();
                String name = headerFieldType.getString(NAME, null);
                int id = headerFieldType.getInt(ID, NO_ID);
                if (id == NO_ID) {
                    log.warn("Can't get id from header type field {}", jsonValue);
                    return;
                }
                if (name == null) {
                    log.warn("Can't get name from header type field {}", jsonValue);
                    return;
                }
                List<Bmv2HeaderFieldTypeModel> fields = Lists.newArrayList();
                headerFieldType.get(FIELDS).asArray().forEach(fieldValue -> {
                    JsonArray fieldInfo = fieldValue.asArray();
                    boolean signed = false;
                    if (fieldInfo.size() == SIZE_WITH_SIGNED_FLAG) {
                        // 3-tuple value, third value is a boolean value
                        // true if the field is signed; otherwise false
                        signed = fieldInfo.get(FIELD_SIGNED_INDEX).asBoolean();
                    }
                    fields.add(new Bmv2HeaderFieldTypeModel(fieldInfo.get(FIELD_NAME_INDEX).asString(),
                                                            fieldInfo.get(FIELD_BIT_WIDTH_INDEX).asInt(),
                                                            signed));
                });
                headerTypeModels.add(new Bmv2HeaderTypeModel(name, id, fields));
            });
            return headerTypeModels;
        }
    }

    /**
     * Parser for BMv2 header stacks.
     */
    private static class HeaderStackParser {
        private static final String HEADER_STACK = "header_stacks";
        private static final String HEADER_IDS = "header_ids";

        /**
         * Parser header stacks, return header-id to stack index mapping.
         *
         * @param jsonObject BMv2 json config
         * @return header-id to stack index mapping
         */
        private static Map<Integer, Integer> parse(JsonObject jsonObject) {
            Map<Integer, Integer> headerIdToIndex = Maps.newHashMap();
            jsonObject.get(HEADER_STACK).asArray().forEach(jsonValue -> {
                JsonArray headerIds = jsonValue.asObject().get(HEADER_IDS).asArray();
                int index = 0;
                for (JsonValue id : headerIds.values()) {
                    headerIdToIndex.put(id.asInt(), index);
                    index++;
                }
            });
            return headerIdToIndex;
        }
    }

    /**
     * Parser for BMv2 headers.
     */
    private static class HeadersParser {
        private static final String HEADERS = "headers";
        private static final String HEADER_TYPE = "header_type";
        private static final String METADATA = "metadata";
        private static final String DEFAULT_HEADER_TYPE = "";
        private static final Integer DEFAULT_HEADER_INDEX = 0;

        private static List<Bmv2HeaderModel> parse(JsonObject jsonObject,
                                                   List<Bmv2HeaderTypeModel> headerTypeModels,
                                                   Map<Integer, Integer> headerIdToIndex) {
            List<Bmv2HeaderModel> headerModels = Lists.newArrayList();

            jsonObject.get(HEADERS).asArray().forEach(jsonValue -> {
                JsonObject header = jsonValue.asObject();
                String name = header.getString(NAME, null);
                int id = header.getInt(ID, NO_ID);
                String headerTypeName = header.getString(HEADER_TYPE, DEFAULT_HEADER_TYPE);
                boolean isMetadata = header.getBoolean(METADATA, false);

                if (name == null || id == -1) {
                    log.warn("Can't get name or id from header {}", header);
                    return;
                }
                Bmv2HeaderTypeModel headerTypeModel = headerTypeModels.stream()
                        .filter(model -> model.name().equals(headerTypeName))
                        .findFirst()
                        .orElse(null);

                if (headerTypeModel == null) {
                    log.warn("Can't get header type model {} from header {}", headerTypeName, header);
                    return;
                }

                Integer index = headerIdToIndex.get(id);

                // No index for this header, set to default
                if (index == null) {
                    index = DEFAULT_HEADER_INDEX;
                }
                headerModels.add(new Bmv2HeaderModel(name, id, index, headerTypeModel, isMetadata));
            });

            return headerModels;
        }
    }

    /**
     * Parser for BMv2 actions.
     */
    private static class ActionsParser {
        private static final String ACTIONS = "actions";
        private static final String RUNTIME_DATA = "runtime_data";
        private static final String BITWIDTH = "bitwidth";

        private static List<Bmv2ActionModel> parse(JsonObject jsonObject) {
            List<Bmv2ActionModel> actionModels = Lists.newArrayList();

            jsonObject.get(ACTIONS).asArray().forEach(jsonValue -> {
                JsonObject action = jsonValue.asObject();
                String name = action.getString(NAME, null);
                int id = action.getInt(ID, NO_ID);
                List<Bmv2ActionParamModel> paramModels = Lists.newArrayList();
                action.get(RUNTIME_DATA).asArray().forEach(paramValue -> {
                    JsonObject paramInfo = paramValue.asObject();
                    String paramName = paramInfo.getString(NAME, null);
                    int bitWidth = paramInfo.getInt(BITWIDTH, -1);

                    if (paramName == null || bitWidth == -1) {
                        log.warn("Can't get name or bit width from runtime data {}", paramInfo);
                        return;
                    }
                    paramModels.add(new Bmv2ActionParamModel(paramName, bitWidth));
                });

                actionModels.add(new Bmv2ActionModel(name, id, paramModels));
            });

            return actionModels;
        }
    }

    /**
     * Parser for BMv2 tables.
     */
    private static class TablesParser {
        private static final String PIPELINES = "pipelines";
        private static final String TABLES = "tables";
        private static final String KEY = "key";
        private static final String MATCH_TYPE = "match_type";
        private static final String TARGET = "target";
        private static final int TARGET_HEADER_INDEX = 0;
        private static final int TARGET_FIELD_INDEX = 1;
        private static final String ACTIONS = "actions";
        private static final String MAX_SIZE = "max_size";
        private static final int DEFAULT_MAX_SIZE = 0;
        private static final String WITH_COUNTERS = "with_counters";
        private static final String SUPPORT_TIMEOUT = "support_timeout";

        private static List<Bmv2TableModel> parse(JsonObject jsonObject,
                                                  List<Bmv2HeaderModel> headerModels,
                                                  List<Bmv2ActionModel> actionModels) {
            List<Bmv2TableModel> tableModels = Lists.newArrayList();
            jsonObject.get(PIPELINES).asArray().forEach(pipelineVal -> {
                JsonObject pipeline = pipelineVal.asObject();
                pipeline.get(TABLES).asArray().forEach(tableVal -> {
                    JsonObject table = tableVal.asObject();
                    String tableName = table.getString(NAME, null);
                    int tableId = table.getInt(ID, NO_ID);
                    int maxSize = table.getInt(MAX_SIZE, DEFAULT_MAX_SIZE);
                    boolean hasCounters = table.getBoolean(WITH_COUNTERS, false);
                    boolean suppportAging = table.getBoolean(SUPPORT_TIMEOUT, false);

                    // Match field
                    Set<Bmv2TableMatchFieldModel> matchFieldModels =
                            Sets.newHashSet();
                    table.get(KEY).asArray().forEach(keyVal -> {
                        JsonObject key = keyVal.asObject();
                        String matchTypeName = key.getString(MATCH_TYPE, null);

                        if (matchTypeName == null) {
                            log.warn("Can't find match type from key {}", key);
                            return;
                        }
                        PiMatchType matchType = PiMatchType.valueOf(matchTypeName.toUpperCase());

                        // convert target array to Bmv2HeaderFieldTypeModel
                        // e.g. ["ethernet", "dst"]
                        JsonArray targetArray = key.get(TARGET).asArray();
                        Bmv2HeaderFieldModel matchField;

                        String headerName = targetArray.get(TARGET_HEADER_INDEX).asString();
                        String fieldName = targetArray.get(TARGET_FIELD_INDEX).asString();

                        Bmv2HeaderModel headerModel = headerModels.stream()
                                .filter(hm -> hm.name().equals(headerName))
                                .findAny()
                                .orElse(null);

                        if (headerModel == null) {
                            log.warn("Can't find header {} for table {}", headerName, tableName);
                            return;
                        }
                        Bmv2HeaderFieldTypeModel fieldModel =
                                (Bmv2HeaderFieldTypeModel) headerModel.type()
                                        .field(fieldName)
                                        .orElse(null);

                        if (fieldModel == null) {
                            log.warn("Can't find field {} from header {}", fieldName, headerName);
                            return;
                        }
                        matchField = new Bmv2HeaderFieldModel(headerModel, fieldModel);
                        matchFieldModels.add(new Bmv2TableMatchFieldModel(matchType, matchField));
                    });

                    // Actions
                    Set<Bmv2ActionModel> actions = Sets.newHashSet();
                    table.get(ACTIONS).asArray().forEach(actionVal -> {
                        String actionName = actionVal.asString();
                        Bmv2ActionModel action = actionModels.stream()
                                .filter(am -> am.name().equals(actionName))
                                .findAny()
                                .orElse(null);
                        if (action == null) {
                            log.warn("Can't find action {}", actionName);
                            return;
                        }
                        actions.add(action);
                    });

                    tableModels.add(new Bmv2TableModel(tableName, tableId,
                                                       maxSize, hasCounters,
                                                       suppportAging,
                                                       matchFieldModels, actions));
                });
            });

            return tableModels;
        }
    }
}
