/*
 * Copyright 2015-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.inbandtelemetry.app.ui;

import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.ImmutableSet;
import org.onosproject.inbandtelemetry.api.IntIntent;
import org.onosproject.inbandtelemetry.api.IntIntentId;
import org.onosproject.inbandtelemetry.api.IntService;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.criteria.IPCriterion;
import org.onosproject.net.flow.criteria.TcpPortCriterion;
import org.onosproject.net.flow.criteria.UdpPortCriterion;
import org.onosproject.ui.RequestHandler;
import org.onosproject.ui.UiMessageHandler;
import org.onosproject.ui.table.TableModel;
import org.onosproject.ui.table.TableRequestHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.Map;
import java.util.Set;

/**
 * Message handler for installed INT intents table in the application UI.
 */
public class IntAppTableMessageHandler extends UiMessageHandler {
    private static final String INT_APP_INT_INTENT = "intAppIntIntent";
    private static final String INT_APP_INT_INTENT_DATA_REQUEST = INT_APP_INT_INTENT + "DataRequest";
    private static final String INT_APP_INT_INTENT_DATA_RESPONSE = INT_APP_INT_INTENT + "DataResponse";

    private static final String INT_APP_DEL_INT_INTENT_REQ = "intAppDelIntIntentRequest";

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

    private static final String ID = "id";
    private static final String SRC_ADDR = "srcAddr";
    private static final String DST_ADDR = "dstAddr";
    private static final String SRC_PORT = "srcPort";
    private static final String DST_PORT = "dstPort";
    private static final String PROTOCOL = "protocol";
    private static final String METADATA = "metadata";

    private static final String[] COLUMN_IDS = {ID, SRC_ADDR, DST_ADDR, SRC_PORT, DST_PORT, PROTOCOL, METADATA};

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

    protected IntService intService;

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

    // handler for table requests
    private final class IntAppIntIntentRequestHandler extends TableRequestHandler {

        private IntAppIntIntentRequestHandler() {
            super(INT_APP_INT_INTENT_DATA_REQUEST, INT_APP_INT_INTENT_DATA_RESPONSE, INT_APP_INT_INTENT);
        }

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

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

        private Map<IntIntentId, IntIntent> getAllIntIntents() {
            intService = get(IntService.class);
            return intService.getIntIntents();
        }

        @Override
        protected void populateTable(TableModel tm, ObjectNode payload) {
            Map<IntIntentId, IntIntent> intentMap = getAllIntIntents();
            intentMap.entrySet().forEach(entry ->
                                                 populateRow(tm.addRow(), entry.getKey(), entry.getValue()));
        }

        private void populateRow(TableModel.Row row, IntIntentId intentId, IntIntent intent) {
            IPCriterion ip4Src = (IPCriterion) intent.selector().getCriterion(Criterion.Type.IPV4_SRC);
            IPCriterion ip4Dst = (IPCriterion) intent.selector().getCriterion(Criterion.Type.IPV4_DST);
            TcpPortCriterion tcpSrcPort = (TcpPortCriterion) intent.selector().getCriterion(Criterion.Type.TCP_SRC);
            TcpPortCriterion tcpDstPort = (TcpPortCriterion) intent.selector().getCriterion(Criterion.Type.TCP_DST);
            UdpPortCriterion udpSrcPort = (UdpPortCriterion) intent.selector().getCriterion(Criterion.Type.UDP_SRC);
            UdpPortCriterion udpDstPort = (UdpPortCriterion) intent.selector().getCriterion(Criterion.Type.UDP_DST);
            Set<IntIntent.IntMetadataType> metadataTypes = intent.metadataTypes();
            row.cell(ID, intentId.toString())
                    .cell(SRC_ADDR, ip4Src == null ? "N/A" : ip4Src.ip().toString())
                    .cell(DST_ADDR, ip4Dst == null ? "N/A" : ip4Dst.ip().toString());
            if (tcpSrcPort != null || tcpDstPort != null) {
                row.cell(PROTOCOL, "TCP")
                        .cell(SRC_PORT, tcpSrcPort == null ? "N/A" : tcpSrcPort.tcpPort().toString())
                        .cell(DST_PORT, tcpDstPort == null ? "N/A" : tcpDstPort.tcpPort().toString());
            } else if (udpSrcPort != null || udpDstPort != null) {
                row.cell(PROTOCOL, "UDP")
                        .cell(SRC_PORT, udpSrcPort == null ? "N/A" : udpSrcPort.udpPort().toString())
                        .cell(DST_PORT, udpDstPort == null ? "N/A" : udpDstPort.udpPort().toString());
            } else {
                row.cell(PROTOCOL, "N/A")
                        .cell(SRC_PORT, "N/A")
                        .cell(DST_PORT, "N/A");
            }
            String metaStr = "";
            for (IntIntent.IntMetadataType metadataType : metadataTypes) {
                metaStr += metadataType.toString();
                metaStr += ", ";
            }
            row.cell(METADATA, metaStr);
        }
    }

    private final class IntAppDelIntIntentRequestHandler extends RequestHandler {

        private IntAppDelIntIntentRequestHandler() {
            super(INT_APP_DEL_INT_INTENT_REQ);
        }

        @Override
        public void process(ObjectNode payload) {
            intService = get(IntService.class);
            if (payload.get(ID) != null) {
                intService.removeIntIntent(IntIntentId.valueOf(payload.get(ID).asLong()));
            }
        }
    }
}
