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

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.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.net.flow.instructions.Instructions;
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 DEV_ID = "devId";

    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 SPACE = " ";
    private static final String COLON = ":";
    private static final String ANGLE_O = "<";
    private static final String ANGLE_C = ">";
    private static final String SQUARE_O = "[";
    private static final String SQUARE_C = "]";

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

    // json structure keys
    private static final String IMMED = "immed";
    private static final String DEFER = "defer";
    private static final String METER = "meter";
    private static final String TABLE = "table";
    private static final String META = "meta";
    private static final String CLEARDEF = "clearDef";

    // TODO: replace the use of the following constants with localized text
    private static final String MSG_NO_SELECTOR =
            "(No traffic selector criteria for this flow)";
    private static final String MSG_NO_TREATMENT =
            "(No traffic treatment instructions for this flow)";
    private static final String NO_ROWS_NO_FLOWS = "No flows found";

    private static final String CRITERIA = "Criteria";
    private static final String TREATMENT_INSTRUCTIONS = "Treatment Instructions";
    private static final String IMM = "imm";
    private static final String DEF = "def";
    private static final String METERED = "metered";
    private static final String TRANSITION = "transition";
    private static final String METADATA = "metadata";
    private static final String CLEARED = "cleared";
    private static final String UNKNOWN = "Unknown";


    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 void removeTrailingComma(StringBuilder sb) {
        int pos = sb.lastIndexOf(COMMA);
        sb.delete(pos, sb.length());
    }

    // 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 + SPACE + ANGLE_O + id + ANGLE_C;
        }
        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 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_NO_FLOWS;
        }

        @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, DEV_ID);
            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 MSG_NO_SELECTOR;
                }

                StringBuilder sb = new StringBuilder();
                if (!shortFormat) {
                    sb.append(CRITERIA).append(COLON).append(SPACE);
                }

                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 &&
                        treatment.writeMetadata() == null) {
                    return MSG_NO_TREATMENT;
                }

                StringBuilder sb = new StringBuilder();

                if (!shortFormat) {
                    sb.append(TREATMENT_INSTRUCTIONS).append(COLON).append(SPACE);
                }

                formatInstructs(sb, imm, IMM);
                formatInstructs(sb, def, DEF);

                addLabVal(sb, METERED, treatment.metered());
                addLabVal(sb, TRANSITION, treatment.tableTransition());
                addLabVal(sb, METADATA, treatment.writeMetadata());

                sb.append(CLEARED).append(COLON)
                        .append(treatment.clearedDeferred());

                return sb.toString();
            }

            private void addLabVal(StringBuilder sb, String label, Instruction value) {
                if (value != null) {
                    sb.append(label).append(COLON).append(value).append(COMMA);
                }
            }
        }

        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).append(SQUARE_O);
                for (Instruction i : instructs) {
                    sb.append(renderInstructionForDisplay(i)).append(COMMA);
                }
                removeTrailingComma(sb);
                sb.append(SQUARE_C).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();
        }

        @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));

                data.put(STATE, EnumFormatter.INSTANCE.format(flow.state()));
                data.put(BYTES, NumberFormatter.INTEGER.format(flow.bytes()));
                data.put(PACKETS, NumberFormatter.INTEGER.format(flow.packets()));
                data.put(DURATION, NumberFormatter.INTEGER.format(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, flow.isPermanent());

                data.set(SELECTOR, jsonCriteria(flow));
                data.set(TREATMENT, jsonTreatment(flow));

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

        private ArrayNode jsonCriteria(FlowEntry flow) {
            ArrayNode crits = arrayNode();
            for (Criterion c : flow.selector().criteria()) {
                crits.add(c.toString());
            }
            return crits;
        }

        private ObjectNode jsonTreatment(FlowEntry flow) {
            ObjectNode treat = objectNode();
            TrafficTreatment treatment = flow.treatment();
            List<Instruction> imm = treatment.immediate();
            List<Instruction> def = treatment.deferred();
            Instructions.MeterInstruction meter = treatment.metered();
            Instructions.TableTypeTransition table = treatment.tableTransition();
            Instructions.MetadataInstruction meta = treatment.writeMetadata();

            if (!imm.isEmpty()) {
                treat.set(IMMED, jsonInstrList(imm));
            }
            if (!def.isEmpty()) {
                treat.set(DEFER, jsonInstrList(def));
            }
            if (meter != null) {
                treat.put(METER, meter.toString());
            }
            if (table != null) {
                treat.put(TABLE, table.toString());
            }
            if (meta != null) {
                treat.put(META, meta.toString());
            }
            treat.put(CLEARDEF, treatment.clearedDeferred());
            return treat;
        }

        private ArrayNode jsonInstrList(List<Instruction> instructions) {
            ArrayNode array = arrayNode();
            for (Instruction i : instructions) {
                array.add(renderInstructionForDisplay(i));
            }
            return array;
        }
    }

    // package private to allow unit test access...
    String renderInstructionForDisplay(Instruction instr) {

        // special handling for Extension Instruction Wrappers...
        if (instr instanceof Instructions.ExtensionInstructionWrapper) {
            Instructions.ExtensionInstructionWrapper wrap =
                    (Instructions.ExtensionInstructionWrapper) instr;
            return wrap.type() + COLON + wrap.extensionInstruction();
        }

        // special handling of other instruction classes could be placed here

        // default to the natural string representation otherwise
        return instr.toString();
    }
}
