/*
 * 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.CoreService;
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 IDLE_TIMEOUT = "idleTimeout";
    private static final String HARD_TIMEOUT = "hardTimeout";
    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 = "*";

    // 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,
            IDLE_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) {
            appId = get(CoreService.class).getAppId(id);
            if (appId == null) {
                return UNKNOWN + SPACE + ANGLE_O + id + ANGLE_C;
            }
            lookup.put(id, appId);
        }
        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(IDLE_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(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(IDLE_TIMEOUT, flow.timeout());
                data.put(HARD_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(i.toString());
            }
            return array;
        }
    }

    // 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";
}
