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

import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import org.onosproject.codec.CodecContext;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.flow.TableStatisticsEntry;
import org.onosproject.net.pi.model.PiPipeconf;
import org.onosproject.net.pi.model.PiPipeconfId;
import org.onosproject.net.pi.model.PiPipelineModel;
import org.onosproject.net.pi.service.PiPipeconfService;
import org.onosproject.ui.RequestHandler;
import org.onosproject.ui.UiMessageHandler;
import org.onosproject.ui.table.TableModel;
import org.onosproject.ui.table.TableRequestHandler;

import org.onosproject.ui.table.cell.DefaultCellFormatter;
import org.onosproject.ui.table.cell.NumberFormatter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.Optional;

public class PipeconfViewMessageHandler extends UiMessageHandler {
    private static final Logger log =
            LoggerFactory.getLogger(PipeconfViewMessageHandler.class);
    private static final String PIPECONF_REQUEST = "pipeconfRequest";
    private static final String PIPECONF_RESP = "pipeConfResponse";
    private static final String DEVICE_ID = "devId";
    private static final String PIPECONF = "pipeconf";
    private static final String PIPELINE_MODEL = "pipelineModel";
    private static final String NO_PIPECONF_RESP = "noPipeconfResp";

    private static final String TABLESTAT_DATA_REQ = "tableStatDataRequest";
    private static final String TABLESTAT_DATA_RESP = "tableStatDataResponse";
    private static final String TABLESTATS = "tableStats";
    private static final String TABLE_NAME = "table";
    private static final String ACTIVE = "active";
    private static final String LOOKEDUP = "lookedup";
    private static final String HASLOOKEDUP = "haslookedup";
    private static final String MATCHED = "matched";
    private static final String HASMAXSIZE = "hasmaxsize";
    private static final String MAXSIZE = "maxsize";

    private static final String[] COL_IDS = {
            TABLE_NAME, ACTIVE, HASLOOKEDUP, LOOKEDUP, MATCHED, HASMAXSIZE, MAXSIZE
    };


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

    private class PipeconfRequestHandler extends RequestHandler {

        PipeconfRequestHandler() {
            super(PIPECONF_REQUEST);
        }

        @Override
        public void process(ObjectNode payload) {
            PiPipeconfService piPipeconfService = get(PiPipeconfService.class);
            DeviceService deviceService = get(DeviceService.class);
            ObjectNode responseData = objectNode();
            String devId = string(payload, DEVICE_ID);
            if (devId == null || devId.isEmpty()) {
                log.warn("{}: Invalid device id", PIPECONF_REQUEST);
                sendMessage(NO_PIPECONF_RESP, null);
                return;
            }
            DeviceId deviceId = DeviceId.deviceId(devId);
            Optional<PiPipeconfId> pipeconfId = piPipeconfService.ofDevice(deviceId);
            if (!pipeconfId.isPresent()) {
                log.warn("{}: Can't find pipeconf id for device {}", PIPECONF_REQUEST, deviceId);
                sendMessage(NO_PIPECONF_RESP, null);
                return;
            }

            Optional<PiPipeconf> pipeconf = piPipeconfService.getPipeconf(pipeconfId.get());
            if (!pipeconf.isPresent()) {
                log.warn("{}: Can't find pipeconf {}", PIPECONF_REQUEST, pipeconfId);
                sendMessage(NO_PIPECONF_RESP, null);
                return;
            }
            CodecContext codecContext = getJsonCodecContext();

            ObjectNode pipeconfData = codecContext.encode(pipeconf.get(), PiPipeconf.class);
            responseData.set(PIPECONF, pipeconfData);

            // Filtered out models not exists in interpreter
            // usually they generated by compiler automatically
            Device device = deviceService.getDevice(deviceId);
            if (device == null || !deviceService.isAvailable(deviceId)) {
                log.warn("{}: Device {} is not available", PIPECONF_REQUEST, deviceId);
                sendMessage(NO_PIPECONF_RESP, null);
                return;
            }
            PiPipelineModel pipelineModel = pipeconf.get().pipelineModel();

            ObjectNode pipelineModelData =
                    codecContext.encode(pipelineModel, PiPipelineModel.class);
            responseData.set(PIPELINE_MODEL, pipelineModelData);

            sendMessage(PIPECONF_RESP, responseData);
        }
    }

    private class TableStatsHandler extends TableRequestHandler {

        TableStatsHandler() {
            super(TABLESTAT_DATA_REQ, TABLESTAT_DATA_RESP, TABLESTATS);
        }

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

        @Override
        protected String defaultColumnId() {
            return TABLE_NAME;
        }

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

        @Override
        protected TableModel createTableModel() {
            TableModel tm = super.createTableModel();
            tm.setFormatter(TABLE_NAME, DefaultCellFormatter.INSTANCE);
            tm.setFormatter(ACTIVE, NumberFormatter.INTEGER);
            tm.setFormatter(HASLOOKEDUP, DefaultCellFormatter.INSTANCE);
            tm.setFormatter(LOOKEDUP, NumberFormatter.INTEGER);
            tm.setFormatter(MATCHED, NumberFormatter.INTEGER);
            tm.setFormatter(HASMAXSIZE, DefaultCellFormatter.INSTANCE);
            tm.setFormatter(MAXSIZE, NumberFormatter.INTEGER);
            return tm;
        }

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

                Iterable<TableStatisticsEntry> stats = flowService.getFlowTableStatistics(deviceId);
                for (TableStatisticsEntry stat : stats) {
                    populateRow(tm.addRow(), stat);
                }
            }
        }

        private void populateRow(TableModel.Row row, TableStatisticsEntry tableStat) {
            row.cell(TABLE_NAME, tableStat.table())
                .cell(ACTIVE, tableStat.activeFlowEntries())
                .cell(HASLOOKEDUP, tableStat.hasPacketsLookedup())
                .cell(LOOKEDUP, tableStat.packetsLookedup())
                .cell(MATCHED, tableStat.packetsMatched())
                .cell(HASMAXSIZE, tableStat.hasMaxSize())
                .cell(MAXSIZE, tableStat.maxSize());
        }
    }
}
