/*
 * 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.mapping.web.gui;

import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import org.onosproject.mapping.MappingEntry;
import org.onosproject.mapping.MappingService;
import org.onosproject.mapping.MappingTreatment;
import org.onosproject.mapping.addresses.MappingAddress;
import org.onosproject.mapping.instructions.MappingInstruction;
import org.onosproject.mapping.instructions.MulticastMappingInstruction;
import org.onosproject.mapping.instructions.MulticastMappingInstruction.MulticastType;
import org.onosproject.mapping.instructions.UnicastMappingInstruction;
import org.onosproject.mapping.instructions.UnicastMappingInstruction.UnicastType;
import org.onosproject.net.DeviceId;
import org.onosproject.ui.RequestHandler;
import org.onosproject.ui.UiMessageHandler;
import org.onosproject.ui.table.CellFormatter;
import org.onosproject.ui.table.TableModel;
import org.onosproject.ui.table.TableRequestHandler;
import org.onosproject.ui.table.cell.EnumFormatter;
import org.onosproject.ui.table.cell.HexLongFormatter;

import java.util.Collection;

import static org.onosproject.mapping.MappingStore.Type.MAP_CACHE;
import static org.onosproject.mapping.MappingStore.Type.MAP_DATABASE;
import static org.onosproject.mapping.instructions.MappingInstruction.Type.MULTICAST;
import static org.onosproject.mapping.instructions.MappingInstruction.Type.UNICAST;

/**
 * Message handler for mapping management view related messages.
 */
public class MappingsViewMessageHandler extends UiMessageHandler {

    private static final String MAPPING_DATA_REQ = "mappingDataRequest";
    private static final String MAPPING_DATA_RESP = "mappingDataResponse";
    private static final String MAPPINGS = "mappings";

    private static final String MAPPING_DETAIL_REQ = "mappingDetailsRequest";
    private static final String MAPPING_DETAIL_RESP = "mappingDetailsResponse";
    private static final String DETAILS = "details";

    private static final String ID = "id";
    private static final String MAPPING_ID = "mappingId";
    private static final String MAPPING_KEY = "mappingKey";
    private static final String MAPPING_VALUE = "mappingValue";
    private static final String MAPPING_ACTION = "mappingAction";
    private static final String TYPE = "type";
    private static final String STATE = "state";
    private static final String DATABASE = "database";
    private static final String CACHE = "cache";
    private static final String MAPPING_TREATMENTS = "mappingTreatments";

    private static final String MAPPING_ADDRESS = "address";
    private static final String UNICAST_WEIGHT = "unicastWeight";
    private static final String UNICAST_PRIORITY = "unicastPriority";
    private static final String MULTICAST_WEIGHT = "multicastWeight";
    private static final String MULTICAST_PRIORITY = "multicastPriority";

    private static final String COMMA = ", ";
    private static final String OX = "0x";
    private static final String EMPTY = "";

    private static final String NULL_ADDRESS_MSG = "(No mapping address for this mapping)";

    private static final String[] COL_IDS = {
            ID, MAPPING_KEY, MAPPING_VALUE, STATE, MAPPING_ACTION, TYPE
    };

    @Override
    protected Collection<RequestHandler> createRequestHandlers() {
        return ImmutableSet.of(
                new MappingMessageRequest(),
                new DetailRequestHandler()
        );
    }

    /**
     * Handler for mapping message requests.
     */
    private final class MappingMessageRequest extends TableRequestHandler {

        private static final String NO_ROWS_MESSAGE = "No mappings found";

        private MappingMessageRequest() {
            super(MAPPING_DATA_REQ, MAPPING_DATA_RESP, MAPPINGS);
        }

        @Override
        protected String[] getColumnIds() {
            return COL_IDS;
        }

        @Override
        protected String noRowsMessage(ObjectNode payload) {
            return NO_ROWS_MESSAGE;
        }

        @Override
        protected TableModel createTableModel() {
            TableModel tm = super.createTableModel();
            tm.setFormatter(ID, HexLongFormatter.INSTANCE);
            tm.setFormatter(TYPE, EnumFormatter.INSTANCE);
            tm.setFormatter(STATE, EnumFormatter.INSTANCE);
            tm.setFormatter(MAPPING_KEY, new MappingKeyFormatter());
            return tm;
        }

        @Override
        protected void populateTable(TableModel tm, ObjectNode payload) {
            String uri = string(payload, "devId");
            if (!Strings.isNullOrEmpty(uri)) {
                DeviceId deviceId = DeviceId.deviceId(uri);
                MappingService ms = get(MappingService.class);

                for (MappingEntry mapping : ms.getMappingEntries(MAP_DATABASE, deviceId)) {
                    populateRow(tm.addRow(), mapping, DATABASE);
                }

                for (MappingEntry mapping : ms.getMappingEntries(MAP_CACHE, deviceId)) {
                    populateRow(tm.addRow(), mapping, CACHE);
                }
            }
        }

        private void populateRow(TableModel.Row row, MappingEntry mapping,
                                         String type) {
            row.cell(ID, mapping.id().value())
                    .cell(STATE, mapping.state())
                    .cell(TYPE, type)
                    .cell(MAPPING_ACTION, mapping.value().action())
                    .cell(MAPPING_KEY, mapping);
        }
    }

    /**
     * A formatter for formatting mapping key.
     */
    private final class MappingKeyFormatter implements CellFormatter {

        @Override
        public String format(Object value) {
            MappingEntry mapping = (MappingEntry) value;
            MappingAddress address = mapping.key().address();

            if (address == null) {
                return NULL_ADDRESS_MSG;
            }

            return address.toString();
        }
    }

    /**
     * Handler for detailed mapping message requests.
     */
    private final class DetailRequestHandler extends RequestHandler {

        private DetailRequestHandler() {
            super(MAPPING_DETAIL_REQ);
        }

        private MappingEntry findMappingById(String mappingId) {
            MappingService ms = get(MappingService.class);
            Iterable<MappingEntry> dbEntries = ms.getAllMappingEntries(MAP_DATABASE);
            Iterable<MappingEntry> cacheEntries = ms.getAllMappingEntries(MAP_CACHE);

            for (MappingEntry entry : dbEntries) {
                if (entry.id().toString().equals(mappingId)) {
                    return entry;
                }
            }

            for (MappingEntry entry : cacheEntries) {
                if (entry.id().toString().equals(mappingId)) {
                    return entry;
                }
            }

            return null;
        }

        /**
         * Generates a node object of a given mapping treatment.
         *
         * @param treatment mapping treatment
         * @return node object
         */
        private ObjectNode getTreatmentNode(MappingTreatment treatment) {
            ObjectNode data = objectNode();

            data.put(MAPPING_ADDRESS, treatment.address().toString());

            for (MappingInstruction instruct : treatment.instructions()) {
                if (instruct.type() == UNICAST) {
                    UnicastMappingInstruction unicastInstruct =
                            (UnicastMappingInstruction) instruct;
                    if (unicastInstruct.subtype() == UnicastType.WEIGHT) {
                        data.put(UNICAST_WEIGHT,
                                ((UnicastMappingInstruction.WeightMappingInstruction)
                                        unicastInstruct).weight());
                    }
                    if (unicastInstruct.subtype() == UnicastType.PRIORITY) {
                        data.put(UNICAST_PRIORITY,
                                ((UnicastMappingInstruction.PriorityMappingInstruction)
                                        unicastInstruct).priority());
                    }
                }

                if (instruct.type() == MULTICAST) {
                    MulticastMappingInstruction multicastInstruct =
                            (MulticastMappingInstruction) instruct;
                    if (multicastInstruct.subtype() == MulticastType.WEIGHT) {
                        data.put(MULTICAST_WEIGHT,
                                ((MulticastMappingInstruction.WeightMappingInstruction)
                                        multicastInstruct).weight());
                    }
                    if (multicastInstruct.subtype() == MulticastType.PRIORITY) {
                        data.put(MULTICAST_PRIORITY,
                                ((MulticastMappingInstruction.PriorityMappingInstruction)
                                        multicastInstruct).priority());
                    }
                }

                // TODO: extension address will be handled later
            }

            return data;
        }

        @Override
        public void process(ObjectNode payload) {
            String mappingId = string(payload, MAPPING_ID);
            String type = string(payload, TYPE);
            String strippedFlowId = mappingId.replaceAll(OX, EMPTY);

            MappingEntry mapping = findMappingById(strippedFlowId);
            if (mapping != null) {
                ArrayNode arrayNode = arrayNode();

                for (MappingTreatment treatment : mapping.value().treatments()) {
                    arrayNode.add(getTreatmentNode(treatment));
                }

                ObjectNode detailsNode = objectNode();
                detailsNode.put(MAPPING_ID, mappingId);
                detailsNode.put(STATE, mapping.state().name());
                detailsNode.put(TYPE, type);
                detailsNode.put(MAPPING_ACTION, mapping.value().action().toString());

                ObjectNode keyNode = objectNode();
                keyNode.put(MAPPING_ADDRESS, mapping.key().address().toString());

                ObjectNode valueNode = objectNode();
                valueNode.set(MAPPING_TREATMENTS, arrayNode);

                detailsNode.set(MAPPING_KEY, keyNode);
                detailsNode.set(MAPPING_VALUE, valueNode);

                ObjectNode rootNode = objectNode();
                rootNode.set(DETAILS, detailsNode);
                sendMessage(MAPPING_DETAIL_RESP, rootNode);
            }
        }
    }
}
