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

import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import org.onosproject.app.ApplicationService;
import org.onosproject.core.Application;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.DefaultApplicationId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.instructions.Instruction;
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 org.onosproject.ui.table.cell.NumberFormatter;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;


/**
 * Message handler for flow view related messages.
 */
public class FlowViewMessageHandler extends UiMessageHandler {

    private static final String FLOW_DATA_REQ = "flowDataRequest";
    private static final String FLOW_DATA_RESP = "flowDataResponse";
    private static final String FLOWS = "flows";

    private static final String FLOW_DETAILS_REQ = "flowDetailsRequest";
    private static final String FLOW_DETAILS_RESP = "flowDetailsResponse";
    private static final String DETAILS = "details";
    private static final String FLOW_PRIORITY = "priority";

    private static final String ID = "id";
    private static final String FLOW_ID = "flowId";
    private static final String APP_ID = "appId";
    private static final String APP_NAME = "appName";
    private static final String GROUP_ID = "groupId";
    private static final String TABLE_ID = "tableId";
    private static final String PRIORITY = "priority";
    private static final String SELECTOR_C = "selector_c"; // for table column
    private static final String SELECTOR = "selector";
    private static final String TREATMENT_C = "treatment_c"; // for table column
    private static final String TREATMENT = "treatment";
    private static final String TIMEOUT = "timeout";
    private static final String PERMANENT = "permanent";
    private static final String STATE = "state";
    private static final String PACKETS = "packets";
    private static final String DURATION = "duration";
    private static final String BYTES = "bytes";

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

    private static final String ONOS_PREFIX = "org.onosproject.";
    private static final String ONOS_MARKER = "*";

    private static final String[] COL_IDS = {
            ID,
            STATE,
            BYTES,
            PACKETS,
            DURATION,
            PRIORITY,
            TABLE_ID,
            APP_ID,
            APP_NAME,

            GROUP_ID,
            TIMEOUT,
            PERMANENT,

            SELECTOR_C,
            SELECTOR,
            TREATMENT_C,
            TREATMENT,
    };

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

    private StringBuilder removeTrailingComma(StringBuilder sb) {
        int pos = sb.lastIndexOf(COMMA);
        sb.delete(pos, sb.length());
        return sb;
    }

    // Generate a map of shorts->application IDs
    // (working around deficiency(?) in Application Service API)
    private Map<Short, ApplicationId> appShortMap() {
        Set<Application> apps =
                get(ApplicationService.class).getApplications();

        return apps.stream()
                .collect(Collectors.toMap(a -> a.id().id(), Application::id));
    }

    // Return an application name, based on a lookup of the internal short ID
    private String makeAppName(short id, Map<Short, ApplicationId> lookup) {
        ApplicationId appId = lookup.get(id);
        if (appId == null) {
            return "Unknown <" + id + ">";
        }
        String appName = appId.name();
        return appName.startsWith(ONOS_PREFIX)
                ? appName.replaceFirst(ONOS_PREFIX, ONOS_MARKER) : appName;
    }

    // handler for flow table requests
    private final class FlowDataRequest extends TableRequestHandler {

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

        private FlowDataRequest() {
            super(FLOW_DATA_REQ, FLOW_DATA_RESP, FLOWS);
        }

        @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(STATE, EnumFormatter.INSTANCE);
            tm.setFormatter(BYTES, NumberFormatter.INTEGER);
            tm.setFormatter(PACKETS, NumberFormatter.INTEGER);
            tm.setFormatter(DURATION, NumberFormatter.INTEGER);

            tm.setFormatter(SELECTOR_C, new SelectorShortFormatter());
            tm.setFormatter(SELECTOR, new SelectorFormatter());
            tm.setFormatter(TREATMENT_C, new TreatmentShortFormatter());
            tm.setFormatter(TREATMENT, new TreatmentFormatter());
            return tm;
        }

        @Override
        protected void populateTable(TableModel tm, ObjectNode payload) {
            String uri = string(payload, "devId");
            if (!Strings.isNullOrEmpty(uri)) {
                DeviceId deviceId = DeviceId.deviceId(uri);
                Map<Short, ApplicationId> lookup = appShortMap();
                FlowRuleService frs = get(FlowRuleService.class);

                for (FlowEntry flow : frs.getFlowEntries(deviceId)) {
                    populateRow(tm.addRow(), flow, lookup);
                }
            }
        }

        private void populateRow(TableModel.Row row, FlowEntry flow,
                                 Map<Short, ApplicationId> lookup) {
            row.cell(ID, flow.id().value())
                    .cell(STATE, flow.state())
                    .cell(BYTES, flow.bytes())
                    .cell(PACKETS, flow.packets())
                    .cell(DURATION, flow.life())
                    .cell(PRIORITY, flow.priority())
                    .cell(TABLE_ID, flow.tableId())
                    .cell(APP_ID, flow.appId())
                    .cell(APP_NAME, makeAppName(flow.appId(), lookup))

                    .cell(GROUP_ID, flow.groupId().id())
                    .cell(TIMEOUT, flow.timeout())
                    .cell(PERMANENT, flow.isPermanent())

                    .cell(SELECTOR_C, flow)
                    .cell(SELECTOR, flow)
                    .cell(TREATMENT_C, flow)
                    .cell(TREATMENT, flow);
        }

        private class InternalSelectorFormatter implements CellFormatter {
            private final boolean shortFormat;

            InternalSelectorFormatter(boolean shortFormat) {
                this.shortFormat = shortFormat;
            }

            @Override
            public String format(Object value) {
                FlowEntry flow = (FlowEntry) value;
                Set<Criterion> criteria = flow.selector().criteria();

                if (criteria.isEmpty()) {
                    return "(No traffic selector criteria for this flow)";
                }

                StringBuilder sb = new StringBuilder();
                if (!shortFormat) {
                    sb.append("Criteria: ");
                }

                for (Criterion c : criteria) {
                    sb.append(c).append(COMMA);
                }
                removeTrailingComma(sb);

                return sb.toString();
            }
        }

        private final class SelectorShortFormatter extends InternalSelectorFormatter {
            SelectorShortFormatter() {
                super(true);
            }
        }

        private final class SelectorFormatter extends InternalSelectorFormatter {
            SelectorFormatter() {
                super(false);
            }
        }

        private class InternalTreatmentFormatter implements CellFormatter {
            private final boolean shortFormat;

            InternalTreatmentFormatter(boolean shortFormat) {
                this.shortFormat = shortFormat;
            }

            @Override
            public String format(Object value) {
                FlowEntry flow = (FlowEntry) value;
                TrafficTreatment treatment = flow.treatment();
                List<Instruction> imm = treatment.immediate();
                List<Instruction> def = treatment.deferred();
                if (imm.isEmpty() &&
                        def.isEmpty() &&
                        treatment.metered() == null &&
                        treatment.tableTransition() == null) {
                    return "(No traffic treatment instructions for this flow)";
                }

                StringBuilder sb = new StringBuilder();

                if (!shortFormat) {
                    sb.append("Treatment Instructions: ");
                }

                formatInstructs(sb, imm, "immediate:");
                formatInstructs(sb, def, "deferred:");

                if (treatment.metered() != null) {
                    sb.append("metered:")
                            .append(treatment.metered())
                            .append(COMMA);
                }

                if (treatment.tableTransition() != null) {
                    sb.append("transition:")
                            .append(treatment.tableTransition())
                            .append(COMMA);
                }

                if (treatment.writeMetadata() != null) {
                    sb.append("metadata:")
                            .append(treatment.writeMetadata())
                            .append(COMMA);
                }

                sb.append("cleared:").append(treatment.clearedDeferred());

                return sb.toString();
            }
        }

        private final class TreatmentShortFormatter extends InternalTreatmentFormatter {
            TreatmentShortFormatter() {
                super(true);
            }
        }

        private final class TreatmentFormatter extends InternalTreatmentFormatter {
            TreatmentFormatter() {
                super(false);
            }
        }

        private void formatInstructs(StringBuilder sb,
                                     List<Instruction> instructs,
                                     String type) {
            if (!instructs.isEmpty()) {
                sb.append(type);
                for (Instruction i : instructs) {
                    sb.append(i).append(COMMA);
                }
            }
        }
    }

    private final class DetailRequestHandler extends RequestHandler {
        private DetailRequestHandler() {
            super(FLOW_DETAILS_REQ);
        }

        private FlowEntry findFlowById(String appIdText, String flowId) {
            String strippedFlowId = flowId.replaceAll(OX, EMPTY);
            FlowRuleService fs = get(FlowRuleService.class);
            int appIdInt = Integer.parseInt(appIdText);
            ApplicationId appId = new DefaultApplicationId(appIdInt, DETAILS);
            Iterable<FlowEntry> entries = fs.getFlowEntriesById(appId);

            for (FlowEntry entry : entries) {
                if (entry.id().toString().equals(strippedFlowId)) {
                    return entry;
                }
            }

            return null;
        }

        private String decorateFlowId(FlowRule flow) {
            return OX + flow.id();
        }

        private String decorateGroupId(FlowRule flow) {
            return OX + flow.groupId().id();
        }

        private String getCriteriaString(FlowRule flow) {
            Set<Criterion> criteria = flow.selector().criteria();
            StringBuilder sb = new StringBuilder();
            for (Criterion c : criteria) {
                sb.append(c).append(COMMA);
            }
            removeTrailingComma(sb);
            return sb.toString();
        }

        private String getTreatmentString(FlowRule flow) {
            List<Instruction> instructions = flow.treatment().allInstructions();
            StringBuilder sb = new StringBuilder();
            for (Instruction inst : instructions) {
                sb.append(inst).append(COMMA);
            }
            if (flow.treatment().metered() != null) {
                sb.append(flow.treatment().metered()).append(COMMA);
            }
            if (flow.treatment().tableTransition() != null) {
                sb.append(flow.treatment().tableTransition()).append(COMMA);
            }

            removeTrailingComma(sb);
            return sb.toString();
        }

        @Override
        public void process(ObjectNode payload) {

            String flowId = string(payload, FLOW_ID);
            String appId = string(payload, APP_ID);

            FlowEntry flow = findFlowById(appId, flowId);
            if (flow != null) {
                ObjectNode data = objectNode();

                data.put(FLOW_ID, decorateFlowId(flow));

                // TODO: use formatters for these values..
                data.put(STATE, flow.state().toString());
                data.put(BYTES, flow.bytes());
                data.put(PACKETS, flow.packets());
                data.put(DURATION, flow.life());

                data.put(FLOW_PRIORITY, flow.priority());
                data.put(TABLE_ID, flow.tableId());
                data.put(APP_ID, flow.appId());
                // NOTE: horribly inefficient... make a map and retrieve a single value...
                data.put(APP_NAME, makeAppName(flow.appId(), appShortMap()));

                data.put(GROUP_ID, decorateGroupId(flow));
                data.put(TIMEOUT, flow.hardTimeout());
                data.put(PERMANENT, Boolean.toString(flow.isPermanent()));

                data.put(SELECTOR, getCriteriaString(flow));
                data.put(TREATMENT, getTreatmentString(flow));

                ObjectNode rootNode = objectNode();
                rootNode.set(DETAILS, data);
                sendMessage(FLOW_DETAILS_RESP, rootNode);
            }
        }
    }
}
