/*
 * Copyright 2018-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.openstacktelemetry.codec;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.TpPort;
import org.onlab.packet.VlanId;
import org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.core.CoreService;
import org.onosproject.net.DeviceId;
import org.onosproject.openstacktelemetry.api.FlowInfo;
import org.onosproject.openstacktelemetry.api.StatsInfo;
import org.onosproject.openstacktelemetry.impl.DefaultFlowInfo;
import org.onosproject.openstacktelemetry.impl.DefaultStatsInfo;

import java.util.HashMap;
import java.util.Map;

import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.notNullValue;
import static org.onosproject.net.NetTestTools.APP_ID;
import static org.onosproject.openstacktelemetry.codec.FlowInfoJsonMatcher.matchesFlowInfo;

/**
 * Unit tests for FlowInfo codec.
 */
public class FlowInfoJsonCodecTest {
    MockCodecContext context;
    JsonCodec<FlowInfo> flowInfoCodec;
    JsonCodec<StatsInfo> statsInfoCodec;
    final CoreService mockCoreService = createMock(CoreService.class);
    private static final String REST_APP_ID = "org.onosproject.rest";

    private static final int INPUT_INTERFACE_ID = 1;
    private static final int OUTPUT_INTERFACE_ID = 2;

    private static final int VLAN_ID = 1;
    private static final int PROTOCOL = 1;
    private static final int FLOW_TYPE = 1;
    private static final String DEVICE_ID = "of:00000000000000a1";

    private static final String SRC_IP_ADDRESS = "10.10.10.1";
    private static final int SRC_IP_PREFIX = 24;
    private static final String DST_IP_ADDRESS = "20.20.20.1";
    private static final int DST_IP_PREFIX = 24;
    private static final int SRC_PORT = 1000;
    private static final int DST_PORT = 2000;
    private static final String SRC_MAC_ADDRESS = "AA:BB:CC:DD:EE:FF";
    private static final String DST_MAC_ADDRESS = "FF:EE:DD:CC:BB:AA";

    private static final long LONG_VALUE = 1L;
    private static final int INTEGER_VALUE = 1;
    private static final short SHORT_VALUE = (short) 1;


    @Before
    public void setUp() {
        context = new MockCodecContext();
        flowInfoCodec = new FlowInfoJsonCodec();
        statsInfoCodec = new StatsInfoJsonCodec();

        assertThat(flowInfoCodec, notNullValue());
        assertThat(statsInfoCodec, notNullValue());

        expect(mockCoreService.registerApplication(REST_APP_ID))
                .andReturn(APP_ID).anyTimes();
        replay(mockCoreService);
        context.registerService(CoreService.class, mockCoreService);
    }

    /**
     * Tests the flow info encoding.
     */
    @Test
    public void testEncode() {
        StatsInfo statsInfo = new DefaultStatsInfo.DefaultBuilder()
                                    .withStartupTime(LONG_VALUE)
                                    .withFstPktArrTime(LONG_VALUE)
                                    .withLstPktOffset(INTEGER_VALUE)
                                    .withPrevAccBytes(LONG_VALUE)
                                    .withPrevAccPkts(INTEGER_VALUE)
                                    .withCurrAccBytes(LONG_VALUE)
                                    .withCurrAccPkts(INTEGER_VALUE)
                                    .withErrorPkts(SHORT_VALUE)
                                    .withDropPkts(SHORT_VALUE)
                                    .build();
        FlowInfo flowInfo = new DefaultFlowInfo.DefaultBuilder()
                                    .withFlowType((byte) FLOW_TYPE)
                                    .withDeviceId(DeviceId.deviceId(DEVICE_ID))
                                    .withInputInterfaceId(INPUT_INTERFACE_ID)
                                    .withOutputInterfaceId(OUTPUT_INTERFACE_ID)
                                    .withVlanId(VlanId.vlanId((short) VLAN_ID))
                                    .withSrcIp(IpPrefix.valueOf(
                                            IpAddress.valueOf(SRC_IP_ADDRESS), SRC_IP_PREFIX))
                                    .withDstIp(IpPrefix.valueOf(
                                            IpAddress.valueOf(DST_IP_ADDRESS), DST_IP_PREFIX))
                                    .withSrcPort(TpPort.tpPort(SRC_PORT))
                                    .withDstPort(TpPort.tpPort(DST_PORT))
                                    .withProtocol((byte) PROTOCOL)
                                    .withSrcMac(MacAddress.valueOf(SRC_MAC_ADDRESS))
                                    .withDstMac(MacAddress.valueOf(DST_MAC_ADDRESS))
                                    .withStatsInfo(statsInfo)
                                    .build();

        ObjectNode nodeJson = flowInfoCodec.encode(flowInfo, context);
        assertThat(nodeJson, matchesFlowInfo(flowInfo));
    }

    /**
     * Mock codec context for use in codec unit tests.
     */
    private class MockCodecContext implements CodecContext {
        private final ObjectMapper mapper = new ObjectMapper();
        private final CodecManager manager = new CodecManager();
        private final Map<Class<?>, Object> services = new HashMap<>();

        /**
         * Constructs a new mock codec context.
         */
        public MockCodecContext() {
            manager.activate();
        }

        @Override
        public ObjectMapper mapper() {
            return mapper;
        }

        @Override
        @SuppressWarnings("unchecked")
        public <T> JsonCodec<T> codec(Class<T> entityClass) {
            if (entityClass == FlowInfo.class) {
                return (JsonCodec<T>) flowInfoCodec;
            }
            if (entityClass == StatsInfo.class) {
                return (JsonCodec<T>) statsInfoCodec;
            }
            return manager.getCodec(entityClass);
        }

        @SuppressWarnings("unchecked")
        @Override
        public <T> T getService(Class<T> serviceClass) {
            return (T) services.get(serviceClass);
        }

        // for registering mock services
        public <T> void registerService(Class<T> serviceClass, T impl) {
            services.put(serviceClass, impl);
        }
    }
}
